Comment publier du Web avec msbuild?

216

Visual Studio 2010 dispose d'une commande Publier qui vous permet de publier votre projet d'application Web dans un emplacement de système de fichiers. Je voudrais le faire sur mon serveur de build TeamCity, donc je dois le faire avec le solution runner ou msbuild. J'ai essayé d'utiliser la cible de publication, mais je pense que cela pourrait être pour ClickOnce:

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

Je veux essentiellement faire exactement ce que fait un projet de déploiement Web, mais sans le complément. J'en ai besoin pour compiler le WAP, supprimer tous les fichiers inutiles pour l'exécution, effectuer toutes les transformations web.config et copier la sortie vers un emplacement spécifié.

Ma solution , basée sur la réponse 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
la source
doublon possible: stackoverflow.com/questions/1162253/…
Steven Evers
@SnOrfus J'utilise actuellement des projets de déploiement Web dans VS 2008 (comme je l'ai mentionné dans ma réponse à cette question), mais j'aimerais plutôt essayer d'automatiser la fonction de publication de VS 2010.
jrummell
Cette question semble utile stackoverflow.com/questions/1983575/…
jrummell
2
Juste un petit amendement à votre script: vous utilisez $ (ProjectPath) pour le script de déploiement mais vous voulez vraiment est $ (ProjectDir) sinon vous vous retrouvez avec .csproj \ obj
Troy Hunt
2
À partir de VS2012, c'est beaucoup plus facile: stackoverflow.com/a/13947667/270348
RobSiklos

Réponses:

137

Je l'ai fait fonctionner principalement sans script msbuild personnalisé. Voici les paramètres de configuration de build TeamCity pertinents:

Chemins d'artefact:% system.teamcity.build.workingDir% \ MyProject \ obj \ Debug \ Package \ PackageTmp 
Type de coureur: MSBuild (coureur pour fichiers MSBuild) 
Chemin du fichier de génération: MyProject \ MyProject.csproj 
Répertoire de travail: identique au répertoire d'extraction 
Version MSBuild: Microsoft .NET Framework 4.0 
MSBuild ToolsVersion: 4.0 
Exécuter la plate-forme: x86 
Cibles: Package 
Paramètres de ligne de commande pour MSBuild.exe: / p: Configuration = Debug

Cela compilera, conditionnera (avec la transformation web.config) et enregistrera la sortie sous forme d'artefacts. La seule chose qui manque est de copier la sortie vers un emplacement spécifié, mais cela pourrait être fait dans une autre configuration de build TeamCity avec une dépendance d'artefact ou avec un script msbuild.

Mettre à jour

Voici un script msbuild qui va compiler, empaqueter (avec la transformation web.config) et copier la sortie sur mon serveur intermédiaire

<?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>

Vous pouvez également supprimer les propriétés SolutionName et ProjectName de la balise PropertyGroup et les transmettre à msbuild.

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

Update 2

Étant donné que cette question reçoit toujours beaucoup de trafic, j'ai pensé qu'il valait la peine de mettre à jour ma réponse avec mon script actuel qui utilise Web Deploy (également connu sous le nom de 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>

Dans TeamCity, j'ai des paramètres nommés env.Configuration, env.ProjectNameet env.DeployServiceUrl. Le runner MSBuild a le chemin du fichier de construction et les paramètres sont passés automatiquement (vous n'avez pas besoin de les spécifier dans les paramètres de ligne de commande).

Vous pouvez également l'exécuter à partir de la ligne de commande:

msbuild build.xml /p:Configuration=Staging;ProjectName=MyProject;DeployServiceUrl=http://staging-server/MSDeployAgentService
jrummell
la source
2
merci - cela fonctionne aussi bien directement depuis powershell (excuses pour le formatage - pas de retour chariot dans les commentaires): & msbuild "$ solution" / p: "Configuration = $ configuration"; & msbuild "$ project" / t: Package / p: "Configuration = $ configuration; _PackageTempDir = $ outputfolder"
zcrar70
J'ai essayé l'exemple de votre première mise à jour et il semble que la Packagecible dépende également 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.(en le mentionnant puisque vous écrivez que votre deuxième mise à jour utilise WebDeploy, ce qui pourrait impliquer que la première n'utilise pas encore WebDeploy.)
chiccodoro
@jrummell: Je souhaite déployer mon projet Web Visual Studio sur un serveur Windows distant à partir de TeamCity. Que devrais-je faire. Je suis un débutant et je n'ai aucune idée de ce qu'il faut faire
Nevin Raj Victor
1
Je suis en mesure de faire fonctionner cela sur TeamCity avec des projets d'application Web, mais j'ai également un projet de site Web lié hérité que je dois également publier (sous forme de package) puis utiliser MSDeploy. Si je publie dans VS2013, j'obtiens un package de déploiement, mais MSBuild de la ligne cmd n'en crée pas. Des pensées?
KnowHowSolutions
1
Je ne vois aucune mention du profil de publication ici. Le profil de publication doit être spécifié pour que la transformation web.config correcte soit appliquée. Mise à jour: Nevermind ... cette fonctionnalité a été introduite 2 ans après cette publication. Celui-ci fonctionne probablement encore. Un post ultérieur dans ce fil montre comment publier avec un profil de publication à partir de la ligne de commande.
Triynko
84

À l'aide des profils de déploiement introduits dans VS 2012, vous pouvez publier avec la ligne de commande suivante:

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

Pour plus d'informations sur les paramètres, voir ceci .

Les valeurs du /p:VisualStudioVersionparamètre dépendent de votre version de Visual Studio. Wikipedia a un tableau des versions de Visual Studio et de leurs versions .

Chris
la source
6
À l'aide de VS2012 .NET 3.5, cela n'a pas fonctionné pour le déploiement sur le système de fichiers. Il construit simplement et ne fait aucun déploiement.
Jay Sullivan
2
votre /p:VisualStudioVersion=11.0 m'a sauvé la vie. J'utilise /p:VisualStudioVersion=12.0 pour vs2013 et cela fonctionne très bien.
Seyed Morteza Mousavi
Quelle sera la valeur /p:VisualStudioVersion=?pour VS 2017?
Nishant
script de construction créé 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 ...... Mais toujours obtenir uniquement les DLL pas tous les fichiers comme dans le dossier de publication: (`
Nishant
@Nishant Pour VS 2017, utilisez /p:VisualStudioVersion=15. Je ne sais pas si cela est lié à votre problème de copie de fichiers.
Chris
38

J'ai trouvé une telle solution, fonctionne très bien pour moi:

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

La sauce secrète est la cible _WPPCopyWebApplication.

Alexander Beletsky
la source
1
Qu'est-ce que _WPPCopyWebApplication et comment puis-je l'utiliser? Fichier de configuration xml MSBbuild /
Johnny_D
4
En utilisant VS2012 .NET 3.5, j'ai eu l'erreur error MSB4057: The target "_WPPCopyWebApplication" does not exist in the project. Retirer cette partie a conduit à un déploiement sans déployer de vues
Jay Sullivan
Vous devrez peut-être l'appeler avec un autre /p:VisualStudioVersion=12.0 car la génération utilise les cibles de c: \ program files (x86) \ msbuild \ microsoft \ visualstudio \ VERSION \ Webapplication \ Microsoft.WebApplication.targets, donc peut-être son utilisation d'un ancienne version qui n'a pas la bonne cible.
Jim Wolff,
@FRoZeN J'ai essayé d'utiliser MSBuild en tant que 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. Cela me donne une erreur MSBUILD : error MSB1008: Only one project can be specified. Switch: WebSite/New. Y a-t-il une solution à cela?
Nevin Raj Victor
1
@NevinRajVictor, cette erreur est probable car vous disposez d'un espace dans la valeur DeployIisAppPath. Vous devrez mettre la valeur entre guillemets. par exemple / p: DeployIisAppPath = "Site Web par défaut / Nouveau"
shiitake
27

Je ne connais pas TeamCity, donc j'espère que cela peut fonctionner pour vous.

La meilleure façon que j'ai trouvée pour le faire est avec MSDeploy.exe. Cela fait partie du projet WebDeploy exécuté par Microsoft. Vous pouvez télécharger les morceaux ici .

Avec WebDeploy, vous exécutez la ligne de commande

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

Cela fait la même chose que la commande VS Publish, en copiant uniquement les bits nécessaires dans le dossier de déploiement.

Jeff Siver
la source
Cela semble prometteur. Cependant, il semble que le service de gestion ne soit disponible que sur le serveur 2008. Mon serveur de transfert (sur lequel je souhaite automatiser le déploiement) exécute Windows 7 Pro.
jrummell
2
Il y a deux pièces dans le produit. Les éléments qui s'intègrent directement dans IIS nécessitent Server 2008. Le composant de ligne de commande n'a pas cette exigence; Je l'ai en cours d'exécution sur une boîte Server 2003 que j'utilise pour les déploiements.
Jeff Siver
J'ai fait quelques lectures sur MSDeploy. Je l'ai installé et je travaille sur mon serveur de transfert, merci! Puis-je exécuter MSDeploy à partir d'un script MSBuild?
jrummell
1
fait la même chose que quelle configuration de la commande VS Publish? Quelle méthode de publication - système de fichiers ou autre? Utilise-t-il le fichier MyProject.Publish.xml pour déterminer les fichiers à copier?
Anthony
1
Je viens de lui donner un coup mais il n'a pas fait la même chose que VS Publish. Il a fait la même chose que XCopy, y compris tous les fichiers source.
Louis Somers
13

Avec VisualStudio 2012, il existe un moyen de gérer subj sans publier de profils. Vous pouvez passer le dossier de sortie à l'aide de paramètres. Il fonctionne à la fois avec un chemin absolu et relatif dans le paramètre 'publishUrl'. Vous pouvez utiliser VS100COMNTOOLS, mais vous devez remplacer VisualStudioVersion pour utiliser la cible 'WebPublish' de %ProgramFiles%\MSBuild\Microsoft\VisualStudio\v11.0\WebApplications\Microsoft.WebApplication.targets. Avec VisualStudioVersion 10.0, ce script réussira sans sortie :)

Mise à jour: j'ai réussi à utiliser cette méthode sur un serveur de build avec juste Windows SDK 7.1 installé (pas de Visual Studio 2010 et 2012 sur une machine). Mais j'ai dû suivre ces étapes pour le faire fonctionner:

  1. Rendre le SDK 7.1 de Windows à jour sur une machine à l'aide de la réponse Simmo ( https://stackoverflow.com/a/2907056/2164198 )
  2. Définition de la clé de Registre HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ VisualStudio \ SxS \ VS7 \ 10.0 sur "C: \ Program Files \ Microsoft Visual Studio 10.0 \" (utilisez votre chemin d'accès comme approprié)
  3. Copie du dossier% ProgramFiles% \ MSBuild \ Microsoft \ VisualStudio \ v11.0 de ma machine de développeur vers le serveur de génération

Scénario:

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
la source
Merci pour cette solution - c'est ce que je cherchais: l'option WebPublish avec déploiement du système de fichiers.
woohoo
12

trouvé deux solutions différentes qui fonctionnaient de manière légèrement différente:

1. Cette solution est inspirée de la réponse d'alexanderb [link] . Malheureusement, cela n'a pas fonctionné pour nous - certaines DLL n'ont pas été copiées dans l'OutDir. Nous avons découvert que le remplacement ResolveReferencespar la Buildcible résout le problème - maintenant tous les fichiers nécessaires sont copiés dans l'emplacement OutDir.

msbuild / target: Build; _WPPCopyWebApplication / p: Configuration = Release; OutDir = C: \ Tmp \ myApp \ MyApp.csproj
L'inconvénient de cette solution était le fait que OutDir ne contenait pas seulement des fichiers à publier.

2. La première solution fonctionne bien mais pas comme prévu. Nous voulions avoir la fonctionnalité de publication telle qu'elle est dans Visual Studio IDE - c'est-à-dire que seuls les fichiers qui devraient être publiés seront copiés dans le répertoire de sortie. Comme cela a déjà été mentionné, la première solution copie beaucoup plus de fichiers dans OutDir - le site Web à publier est ensuite stocké dans un _PublishedWebsites/{ProjectName}sous-dossier. La commande suivante résout ce problème: seuls les fichiers à publier seront copiés dans le dossier souhaité. Alors maintenant, vous avez un répertoire qui peut être publié directement - en comparaison avec la première solution, vous économiserez de l'espace sur le disque dur.

msbuild / target: Build; PipelinePreDeployCopyAllFilesToOneFolder / p: Configuration = Release; _PackageTempDir = C: \ Tmp \ myApp \; AutoParameterizationWebConfigConnectionStrings = false MyApp.csproj
AutoParameterizationWebConfigConnectionStrings=falsegarantira que les chaînes de connexion ne seront pas traitées comme des artefacts spéciaux et seront générées correctement - pour plus d'informations, voir le lien .

Pavel Cermak
la source
Votre option n ° 2 m'a aidé à me débarrasser de la _CopyWebApplication obsolète. Vous avez sauvé mon Build-Server après la mise à niveau vers VS 2015. Excellentes recherches. Reconnaissant.
it3xl
Votre option # 2 était parfaite pour mon script de construction.
AnthonyVO
3

Vous devez définir vos environnements

  • <Nom du site Web>
  • <domaine>

et référence mon blog.

  • 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
la source
1

C'est mon fichier batch

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 İŞÇİ
la source
5
Ce serait formidable si vous pouviez détailler votre réponse. Comment votre fichier de commandes résout-il exactement le problème du PO? Merci!
Luís Cruz
1

c'est mon lot de travail

publish-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%

Notez que j'ai installé Visual Studio sur le serveur pour pouvoir exécuter MsBuild.execar les MsBuild.exedossiers dans .Net Framework ne fonctionnent pas.

Alper Ebicoglu
la source
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 ...... Mais je n'obtiens toujours que des DLL, pas la structure de fichiers que je veux. Qu'est ce qui ne va pas avec ça? :(
Nishant
1

Vous pouvez publier la solution avec le chemin souhaité par le code ci-dessous, ici PublishInDFolder est le nom qui a le chemin où nous devons publier (nous devons le créer dans l'image ci-dessous)

Vous pouvez créer un fichier de publication comme celui-ci

Ajoutez ci-dessous 2 lignes de code dans un fichier batch (.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
la source
0

Pour générer la sortie de publication, fournissez un paramètre supplémentaire. msbuild example.sln / p: publishprofile = profilename / p: deployonbuild = true / p: configuration = debug / ou any

Yashwant Mahawar
la source