¿Cómo publicar web con msbuild?

216

Visual Studio 2010 tiene un comando Publicar que le permite publicar su Proyecto de aplicación web en una ubicación del sistema de archivos. Me gustaría hacer esto en mi servidor de compilación TeamCity, así que necesito hacerlo con el corredor de soluciones o msbuild. Intenté usar el objetivo Publicar, pero creo que podría ser para ClickOnce:

msbuild Project.csproj /t:Publish /p:Configuration=Deploy

Básicamente quiero hacer exactamente lo que hace un proyecto de implementación web, pero sin el complemento. Lo necesito para compilar el WAP, eliminar cualquier archivo innecesario para la ejecución, realizar cualquier transformación web.config y copiar el resultado en una ubicación específica.

Mi solución , basada en la respuesta de Jeff Siver

<Target Name="Deploy">
    <MSBuild Projects="$(SolutionFile)" 
             Properties="Configuration=$(Configuration);DeployOnBuild=true;DeployTarget=Package" 
             ContinueOnError="false" />
    <Exec Command="&quot;$(ProjectPath)\obj\$(Configuration)\Package\$(ProjectName).deploy.cmd&quot; /y /m:$(DeployServer) -enableRule:DoNotDeleteRule" 
          ContinueOnError="false" />
</Target>
jrummell
fuente
posible duplicado: stackoverflow.com/questions/1162253/…
Steven Evers
@SnOrfus Actualmente estoy usando Proyectos de implementación web en VS 2008 (como mencioné en mi respuesta a esa pregunta), pero me gustaría intentar automatizar la función de publicación de VS 2010.
jrummell
Esta pregunta parece útil stackoverflow.com/questions/1983575/…
jrummell
2
Solo una pequeña enmienda a su secuencia de comandos: está utilizando $ (ProjectPath) para la secuencia de comandos de implementación, pero realmente desea que sea $ (ProjectDir); de lo contrario, terminará con .csproj \ obj
Troy Hunt
2
A partir de VS2012, esto es mucho más fácil: stackoverflow.com/a/13947667/270348
RobSiklos

Respuestas:

137

Lo tengo principalmente trabajando sin un script personalizado de msbuild. Estas son las configuraciones de configuración relevantes de TeamCity:

Rutas de artefactos:% system.teamcity.build.workingDir% \ MyProject \ obj \ Debug \ Package \ PackageTmp 
Tipo de corredor: MSBuild (Runner para archivos MSBuild) 
Ruta del archivo de compilación: MyProject \ MyProject.csproj 
Directorio de trabajo: igual que el directorio de pago 
Versión de MSBuild: Microsoft .NET Framework 4.0 
MSBuild ToolsVersion: 4.0 
Ejecutar plataforma: x86 
Objetivos: paquete 
Parámetros de línea de comando para MSBuild.exe: / p: Configuración = Depuración

Esto compilará, empaquetará (con la transformación web.config) y guardará la salida como artefactos. Lo único que falta es copiar el resultado en una ubicación específica, pero eso podría hacerse en otra configuración de compilación de TeamCity con una dependencia de artefactos o con un script msbuild.

Actualizar

Aquí hay un script de msbuild que compilará, empaquetará (con la transformación web.config) y copiará la salida a mi servidor provisional

<?xml version="1.0" encoding="utf-8" ?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
        <SolutionName>MySolution</SolutionName>
        <SolutionFile>$(SolutionName).sln</SolutionFile>
        <ProjectName>MyProject</ProjectName>
        <ProjectFile>$(ProjectName)\$(ProjectName).csproj</ProjectFile>
    </PropertyGroup>

    <Target Name="Build" DependsOnTargets="BuildPackage;CopyOutput" />

    <Target Name="BuildPackage">
        <MSBuild Projects="$(SolutionFile)" ContinueOnError="false" Targets="Rebuild" Properties="Configuration=$(Configuration)" />
        <MSBuild Projects="$(ProjectFile)" ContinueOnError="false" Targets="Package" Properties="Configuration=$(Configuration)" />
    </Target>

    <Target Name="CopyOutput">
        <ItemGroup>
            <PackagedFiles Include="$(ProjectName)\obj\$(Configuration)\Package\PackageTmp\**\*.*"/>
        </ItemGroup>
        <Copy SourceFiles="@(PackagedFiles)" DestinationFiles="@(PackagedFiles->'\\build02\wwwroot\$(ProjectName)\$(Configuration)\%(RecursiveDir)%(Filename)%(Extension)')"/>
    </Target>
</Project>

También puede eliminar las propiedades SolutionName y ProjectName de la etiqueta PropertyGroup y pasarlas a msbuild.

msbuild build.xml /p:Configuration=Deploy;SolutionName=MySolution;ProjectName=MyProject

Actualización 2

Dado que esta pregunta todavía recibe una gran cantidad de tráfico, pensé que valía la pena actualizar mi respuesta con mi script actual que usa Web Deploy (también conocido como MSDeploy).

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build" ToolsVersion="4.0">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
    <ProjectFile Condition=" '$(ProjectFile)' == '' ">$(ProjectName)\$(ProjectName).csproj</ProjectFile>
    <DeployServiceUrl Condition=" '$(DeployServiceUrl)' == '' ">http://staging-server/MSDeployAgentService</DeployServiceUrl>
  </PropertyGroup>

  <Target Name="VerifyProperties">
    <!-- Verify that we have values for all required properties -->
    <Error Condition=" '$(ProjectName)' == '' " Text="ProjectName is required." />
  </Target>

  <Target Name="Build" DependsOnTargets="VerifyProperties">
    <!-- Deploy using windows authentication -->
    <MSBuild Projects="$(ProjectFile)"
             Properties="Configuration=$(Configuration);
                             MvcBuildViews=False;
                             DeployOnBuild=true;
                             DeployTarget=MSDeployPublish;
                             CreatePackageOnPublish=True;
                             AllowUntrustedCertificate=True;
                             MSDeployPublishMethod=RemoteAgent;
                             MsDeployServiceUrl=$(DeployServiceUrl);
                             SkipExtraFilesOnServer=True;
                             UserName=;
                             Password=;"
             ContinueOnError="false" />
  </Target>
</Project>

En TeamCity, tengo parámetros con nombre env.Configuration, env.ProjectNamey env.DeployServiceUrl. El corredor MSBuild tiene la ruta del archivo de compilación y los parámetros se pasan automáticamente (no es necesario que los especifique en los parámetros de la línea de comandos).

También puede ejecutarlo desde la línea de comando:

msbuild build.xml /p:Configuration=Staging;ProjectName=MyProject;DeployServiceUrl=http://staging-server/MSDeployAgentService
jrummell
fuente
2
gracias - esto también funciona bien directamente desde powershell (disculpas por el formateo - no hay retornos de carro en los comentarios): & msbuild "$ solution" / p: "Configuration = $ configuration"; & msbuild "$ project" / t: Package / p: "Configuration = $ configuration; _PackageTempDir = $ outputfolder"
zcrar70
PackageProbé el ejemplo de su primera actualización y parece que el objetivo también depende de WebDeploy: error : Package/Publish task Microsoft.Web.Publishing.Tasks.IsCleanMSDeployPackageNeeded failed to load Web Deploy assemblies. Microsoft Web Deploy is not correctly installed on this machine.(Mencionándolo ya que escribe que su segunda actualización usa WebDeploy, lo que podría implicar que la primera aún no usaría WebDeploy).
chiccodoro
@jrummell: Quiero implementar mi proyecto web de Visual Studio en un servidor remoto de Windows desde TeamCity. Qué tengo que hacer. Soy un principiante y no tengo idea de qué hacer
Nevin Raj Victor
1
Puedo hacer que esto funcione en TeamCity con proyectos de aplicaciones web, pero también tengo un PROYECTO de sitio web enlazado heredado que también necesito publicar (como paquete) y luego necesito usar MSDeploy. Si publico dentro de VS2013 obtengo un paquete de implementación, pero MSBuild desde la línea cmd no crea uno. ¿Alguna idea?
KnowHowSolutions
1
No veo ninguna mención del perfil de publicación en esto. El perfil de publicación debe especificarse para que se aplique la transformación web.config correcta. Actualización: No importa ... esa característica se introdujo 2 años después de esta publicación. Este probablemente todavía funciona. La publicación posterior en este hilo muestra cómo publicar con un perfil de publicación desde la línea de comandos.
Triynko
84

Con los perfiles de implementación introducidos en VS 2012, puede publicar con la siguiente línea de comando:

msbuild MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=<profile-name> /p:Password=<insert-password> /p:VisualStudioVersion=11.0

Para obtener más información sobre los parámetros, consulte esto .

Los valores para el /p:VisualStudioVersionparámetro dependen de su versión de Visual Studio. Wikipedia tiene una tabla de lanzamientos de Visual Studio y sus versiones .

Chris
fuente
66
Con VS2012 .NET 3.5, esto no funcionó para la implementación en el sistema de archivos. Simplemente se construye y no se implementa.
Jay Sullivan
2
tu /p:VisualStudioVersion=11.0 me salvó la vida. Uso /p:VisualStudioVersion=12.0 para vs2013 y funciona bien.
Seyed Morteza Mousavi
¿Cuál será el valor /p:VisualStudioVersion=?para VS 2017?
Nishant
script de compilación creado msbuild test.sln /p:DeployOnBuild=True /p:DeployDefaultTarget=WebPublish /p:WebPublishMethod=FileSystem /p:DeleteExistingFiles=True /p:publishUrl=.\build_output1\pub /p:PublishProfile=FolderProfile /p:VisualStudioVersion=11.0 /p:outdir=.\build_output1 ...... Pero aún obteniendo solo archivos DLL, no todos los archivos como en la carpeta de publicación: (`
Nishant
@Nishant Para VS 2017, use /p:VisualStudioVersion=15. No estoy seguro de si esto está relacionado con su problema de copia de archivos.
Chris
38

Se me ocurrió tal solución, funciona muy bien para mí:

msbuild /t:ResolveReferences;_WPPCopyWebApplication /p:BuildingProject=true;OutDir=C:\Temp\build\ Test.csproj

La salsa secreta es _WPPCopyWebApplication target.

Alexander Beletsky
fuente
1
¿Qué es _WPPCopyWebApplication y cómo puedo usarlo? Archivo de configuración MSBbuild xml /
Johnny_D
44
Usando VS2012 .NET 3.5, obtuve el error error MSB4057: The target "_WPPCopyWebApplication" does not exist in the project. Sacar esa parte condujo a un despliegue sin desplegar ninguna vista
Jay Sullivan
Es posible que deba llamarlo con un /p:VisualStudioVersion=12.0 diferente porque la compilación utiliza los objetivos de c: \ archivos de programa (x86) \ msbuild \ microsoft \ visualstudio \ VERSION \ Webapplication \ Microsoft.WebApplication.targets, por lo que tal vez esté utilizando un versión anterior que no tiene el objetivo correcto.
Jim Wolff
@FRoZeN Intenté usar MSBuild como MSBuild.exe C:\BuildAgent\work\4c7b8ac8bc7d723e\WebService.sln /p:Configuration=Release /p:OutputPath=bin /p:DeployOnBuild=True /p:DeployTarget=MSDeployPublish /p:MsDeployServiceUrl=https://204.158.674.5/msdeploy.axd /p:username=Admin /p:password=Password#321 /p:AllowUntrustedCertificate=True /p:DeployIisAppPath=Default WebSite/New /p:MSDeployPublishMethod=WMSVC. Me da un error MSBUILD : error MSB1008: Only one project can be specified. Switch: WebSite/New. ¿Existe alguna solucion para esto?
Nevin Raj Victor
1
@NevinRajVictor ese error es probable porque tiene un espacio en el valor DeployIisAppPath. Deberá poner el valor entre comillas. por ejemplo / p: DeployIisAppPath = "Sitio web predeterminado / Nuevo"
shiitake
27

No conozco TeamCity, así que espero que esto funcione para ti.

La mejor forma en que he encontrado para hacer esto es con MSDeploy.exe. Esto es parte del proyecto WebDeploy ejecutado por Microsoft. Puedes descargar los bits aquí .

Con WebDeploy, ejecuta la línea de comando

msdeploy.exe -verb:sync -source:contentPath=c:\webApp -dest:contentPath=c:\DeployedWebApp

Esto hace lo mismo que el comando VS Publish, copiando solo los bits necesarios en la carpeta de implementación.

Jeff Siver
fuente
Eso parece prometedor. Sin embargo, parece que el Servicio de administración solo está disponible en el servidor 2008. Mi servidor provisional (donde quiero automatizar la implementación) ejecuta Windows 7 Pro.
jrummell
2
Hay dos piezas para el producto. Las piezas que se integran directamente en IIS requieren Server 2008. El componente de línea de comandos no tiene ese requisito; Lo tengo ejecutándose en un cuadro de Server 2003 que uso para las implementaciones.
Jeff Siver
He leído algo sobre MSDeploy. Lo tengo instalado y trabajando en mi servidor provisional, ¡gracias! ¿Puedo ejecutar MSDeploy desde un script de MSBuild?
jrummell
1
hace lo mismo que la configuración del comando VS Publicar? ¿Qué método de publicación - sistema de archivos u otro? ¿Utiliza el archivo MyProject.Publish.xml para determinar qué archivos copiar?
Anthony
1
Acabo de darle una oportunidad, pero no hizo lo mismo que VS Publish. Hizo lo mismo que XCopy, incluidos todos los archivos de origen.
Louis Somers
13

Con VisualStudio 2012 hay una manera de manejar subj sin publicar perfiles. Puede pasar la carpeta de salida utilizando los parámetros. Funciona tanto con la ruta absoluta como con la relativa en el parámetro 'editUrl'. Puede usar VS100COMNTOOLS, sin embargo, debe anular VisualStudioVersion para usar el 'WebPublish' de destino %ProgramFiles%\MSBuild\Microsoft\VisualStudio\v11.0\WebApplications\Microsoft.WebApplication.targets. Con VisualStudioVersion 10.0, este script tendrá éxito sin resultados :)

Actualización: logré usar este método en un servidor de compilación con solo Windows SDK 7.1 instalado (no Visual Studio 2010 y 2012 en una máquina). Pero tuve que seguir estos pasos para que funcione:

  1. Actualice Windows SDK 7.1 en una máquina con Simmo answer ( https://stackoverflow.com/a/2907056/2164198 )
  2. Configuración de la clave de registro HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ VisualStudio \ SxS \ VS7 \ 10.0 a "C: \ Archivos de programa \ Microsoft Visual Studio 10.0 \" (use su ruta según corresponda)
  3. Copiando la carpeta% ProgramFiles% \ MSBuild \ Microsoft \ VisualStudio \ v11.0 de mi máquina de desarrollador para construir el servidor

Guión:

set WORK_DIR=%~dp0
pushd %WORK_DIR%
set OUTPUTS=%WORK_DIR%..\Outputs
set CONFIG=%~1
if "%CONFIG%"=="" set CONFIG=Release
set VSTOOLS="%VS100COMNTOOLS%"
if %VSTOOLS%=="" set "PATH=%PATH%;%WINDIR%\Microsoft.NET\Framework\v4.0.30319" && goto skipvsinit
call "%VSTOOLS:~1,-1%vsvars32.bat"
if errorlevel 1 goto end
:skipvsinit
msbuild.exe Project.csproj /t:WebPublish /p:Configuration=%CONFIG% /p:VisualStudioVersion=11.0 /p:WebPublishMethod=FileSystem /p:publishUrl=%OUTPUTS%\Project
if errorlevel 1 goto end
:end
popd
exit /b %ERRORLEVEL%
Ivan Samygin
fuente
Gracias por esta solución, esto es lo que estaba buscando: la opción WebPublish con implementación del sistema de archivos.
woohoo
12

Encontré dos soluciones diferentes que funcionaron de manera ligeramente diferente:

1. Esta solución está inspirada en la respuesta de alexanderb [enlace] . Desafortunadamente no funcionó para nosotros, algunos dll no fueron copiados al OutDir. Nos dimos cuenta de que la sustitución ResolveReferencescon Builddestino resuelve el problema - ahora todos los archivos necesarios se copian en la ubicación OutDir.

msbuild / target: Build; _WPPCopyWebApplication / p: Configuration = Release; OutDir = C: \ Tmp \ myApp \ MyApp.csproj
La desventaja de esta solución fue el hecho de que OutDir contenía no solo archivos para publicación.

2. La primera solución funciona bien pero no como esperábamos. Queríamos tener la funcionalidad de publicación tal como está en Visual Studio IDE, es decir, solo los archivos que deberían publicarse se copiarán en el directorio de Salida. Como ya se mencionó, la primera solución copia muchos más archivos en OutDir: el sitio web para la publicación se almacena en una _PublishedWebsites/{ProjectName}subcarpeta. El siguiente comando resuelve esto: solo los archivos para publicación se copiarán en la carpeta deseada. Así que ahora tiene un directorio que puede publicarse directamente; en comparación con la primera solución, ahorrará espacio en el disco duro.

msbuild / target: Build; PipelinePreDeployCopyAllFilesToOneFolder / p: Configuration = Release; _PackageTempDir = C: \ Tmp \ myApp \; AutoParameterizationWebConfigConnectionStrings = false MyApp.csproj
AutoParameterizationWebConfigConnectionStrings=falseEl parámetro garantizará que las cadenas de conexión no se manejarán como artefactos especiales y se generarán correctamente; para obtener más información, consulte el enlace .

Pavel Cermak
fuente
Su opción # 2 me ayudó a deshacerme de la obsoleta _CopyWebApplication. Usted rescató mi Build-Server después de la actualización a VS 2015. Gran investigación. Agradecido.
it3xl
Su opción # 2 fue perfecta para mi script de compilación.
AnthonyVO
3

Debes configurar tus entornos

  • <Nombre del sitio web>
  • <dominio>

y haga referencia a mi blog (lo siento, la publicación fue coreana)

  • http://xyz37.blog.me/50124665657
  • http://blog.naver.com/PostSearchList.nhn?SearchText=webdeploy&blogId=xyz37&x=25&y=7

    @ECHO OFF
    :: http://stackoverflow.com/questions/5598668/valid-parameters-for-msdeploy-via-msbuild
    ::-DeployOnBuild -True
    :: -False
    :: 
    ::-DeployTarget -MsDeployPublish
    :: -Package
    :: 
    ::-Configuration -Name of a valid solution configuration
    :: 
    ::-CreatePackageOnPublish -True
    :: -False
    :: 
    ::-DeployIisAppPath -<Web Site Name>/<Folder>
    :: 
    ::-MsDeployServiceUrl -Location of MSDeploy installation you want to use
    :: 
    ::-MsDeployPublishMethod -WMSVC (Web Management Service)
    :: -RemoteAgent
    :: 
    ::-AllowUntrustedCertificate (used with self-signed SSL certificates) -True
    :: -False
    :: 
    ::-UserName
    ::-Password
    SETLOCAL
    
    IF EXIST "%SystemRoot%\Microsoft.NET\Framework\v2.0.50727" SET FXPath="%SystemRoot%\Microsoft.NET\Framework\v2.0.50727"
    IF EXIST "%SystemRoot%\Microsoft.NET\Framework\v3.5" SET FXPath="%SystemRoot%\Microsoft.NET\Framework\v3.5"
    IF EXIST "%SystemRoot%\Microsoft.NET\Framework\v4.0.30319" SET FXPath="%SystemRoot%\Microsoft.NET\Framework\v4.0.30319"
    
    SET targetFile=<web site fullPath ie. .\trunk\WebServer\WebServer.csproj
    SET configuration=Release
    SET msDeployServiceUrl=https://<domain>:8172/MsDeploy.axd
    SET msDeploySite="<WebSite name>"
    SET userName="WebDeploy"
    SET password=%USERNAME%
    SET platform=AnyCPU
    SET msbuild=%FXPath%\MSBuild.exe /MaxCpuCount:%NUMBER_OF_PROCESSORS% /clp:ShowCommandLine
    
    %MSBuild% %targetFile% /p:configuration=%configuration%;Platform=%platform% /p:DeployOnBuild=True /p:DeployTarget=MsDeployPublish /p:CreatePackageOnPublish=False /p:DeployIISAppPath=%msDeploySite% /p:MSDeployPublishMethod=WMSVC /p:MsDeployServiceUrl=%msDeployServiceUrl% /p:AllowUntrustedCertificate=True /p:UserName=%USERNAME% /p:Password=%password% /p:SkipExtraFilesOnServer=True /p:VisualStudioVersion=12.0
    
    IF NOT "%ERRORLEVEL%"=="0" PAUSE 
    ENDLOCAL
Kim Ki Won
fuente
1

Este es mi archivo por lotes

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe C:\Projects\testPublish\testPublish.csproj  /p:DeployOnBuild=true /property:Configuration=Release
if exist "C:\PublishDirectory" rd /q /s "C:\PublishDirectory"
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe -v / -p C:\Projects\testPublish\obj\Release\Package\PackageTmp -c C:\PublishDirectory
cd C:\PublishDirectory\bin 
del *.xml
del *.pdb
Alim İŞÇİ
fuente
55
Sería genial si pudieras detallar tu respuesta. ¿Cómo exactamente su archivo por lotes resuelve el problema del OP? ¡Gracias!
Luís Cruz
1

este es mi lote de trabajo

edit-my-website.bat

SET MSBUILD_PATH="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin"
SET PUBLISH_DIRECTORY="C:\MyWebsitePublished"
SET PROJECT="D:\Github\MyWebSite.csproj"


cd /d %MSBUILD_PATH%
MSBuild %PROJECT%  /p:DeployOnBuild=True /p:DeployDefaultTarget=WebPublish /p:WebPublishMethod=FileSystem /p:DeleteExistingFiles=True /p:publishUrl=%PUBLISH_DIRECTORY%

Tenga en cuenta que instalé Visual Studio en el servidor para poder ejecutarlo MsBuild.exeporque las MsBuild.execarpetas en .Net Framework no funcionan.

Alper Ebicoglu
fuente
msbuild test.sln /p:DeployOnBuild=True /p:DeployDefaultTarget=WebPublish /p:WebPublishMethod=FileSystem /p:DeleteExistingFiles=True /p:publishUrl=.\build_output1\pub /p:PublishProfile=FolderProfile /p:VisualStudioVersion=11.0 /p:outdir=.\build_output1 ...... Pero todavía obtengo solo archivos DLL, no la estructura de archivos que quiero. ¿Qué tiene de malo? :(
Nishant
1

Puede publicar la solución con la ruta deseada por el siguiente código, aquí PublishInDFolder es el nombre que tiene la ruta donde necesitamos publicar (necesitamos crear esto en la siguiente imagen)

Puede crear un archivo de publicación como este

Agregue debajo de 2 líneas de código en el archivo por lotes (.bat)

@echo OFF 
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\VsMSBuildCmd.bat"
MSBuild.exe  D:\\Solution\\DataLink.sln /p:DeployOnBuild=true /p:PublishProfile=PublishInDFolder
pause
pradeep sk
fuente
0

Para generar la salida de publicación, proporcione un parámetro más. msbuild example.sln / p: publishingprofile = nombre del perfil / p: deployonbuild = true / p: configuration = debug / or any

Yashwant Mahawar
fuente