Как публиковать веб с помощью msbuild?

Visual Studio 2010 имеет команду "Опубликовать", которая позволяет опубликовать проект веб-приложения в расположении файловой системы. Я хотел бы сделать это на моем сервере сборки TeamCity, поэтому мне нужно сделать это с помощью решения Runner или msbuild. Я попытался использовать цель публикации, но я думаю, что это может быть для ClickOnce:

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

Я в основном хочу сделать именно то, что делает проект веб-развертывания, но без надстройки. Мне это нужно для компиляции WAP, удаления любых файлов, ненужных для выполнения, выполнения любых преобразований web.config и копирования вывода в указанное место.

Мое решение, основанное на ответе Джеффа Сивера

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

12 ответов

Решение

Я получил это в основном работает без специального скрипта msbuild. Вот соответствующие параметры конфигурации сборки TeamCity:

Пути артефактов: %system.teamcity.build.workingDir%\MyProject\obj\Debug\Package\PackageTmp 
Тип бегуна: MSBuild (Бегунок для файлов MSBuild) 
Путь к файлу сборки: MyProject\MyProject.csproj 
Рабочий каталог: так же, как каталог 
Версия MSBuild: Microsoft .NET Framework 4.0 
MSBuild Tools Версия: 4.0 
Запустить платформу: x86 
Цели: Пакет 
Параметры командной строки для MSBuild.exe: /p:Configuration=Debug

Это скомпилирует, упакует (с преобразованием web.config) и сохранит выходные данные как артефакты. Единственное, чего не хватает, - это скопировать вывод в указанное место, но это можно сделать либо в другой конфигурации сборки TeamCity с зависимостью артефакта, либо с помощью сценария msbuild.

Обновить

Вот скрипт msbuild, который скомпилирует, упакует (с преобразованием web.config) и скопирует вывод на мой промежуточный сервер

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

Вы также можете удалить свойства SolutionName и ProjectName из тега PropertyGroup и передать их в msbuild.

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

Обновление 2

Поскольку этот вопрос все еще получает много трафика, я подумал, что стоит обновить мой ответ с помощью моего текущего сценария, который использует Web Deploy (также известный как 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>

В TeamCity у меня есть параметры с именем env.Configuration, env.ProjectName а также env.DeployServiceUrl, У бегуна MSBuild есть путь к файлу сборки, и параметры передаются автоматически (их не нужно указывать в параметрах командной строки).

Вы также можете запустить его из командной строки:

msbuild build.xml /p:Configuration=Staging;ProjectName=MyProject;DeployServiceUrl=http://staging-server/MSDeployAgentService

Используя профили развертывания, представленные в VS 2012, вы можете опубликовать их с помощью следующей командной строки:

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

Для получения дополнительной информации о параметрах см. Это.

Я придумал такое решение, прекрасно работает для меня:

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

Секретный соус - цель _WPPCopyWebApplication.

Я не знаю TeamCity, поэтому надеюсь, что это сработает для вас.

Лучший способ, который я нашел, это сделать с помощью MSDeploy.exe. Это часть проекта WebDeploy, выполняемого Microsoft. Вы можете скачать биты здесь.

С WebDeploy вы запускаете командную строку

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

Это делает то же самое, что и команда VS Publish, копируя только необходимые биты в папку развертывания.

В VisualStudio 2012 есть способ обработки subj без публикации профилей. Вы можете передать выходную папку, используя параметры. Работает как с абсолютным, так и с относительным путем в параметре publishUrl. Вы можете использовать VS100COMNTOOLS, однако вам нужно переопределить VisualStudioVersion, чтобы использовать целевой "WebPublish" из %ProgramFiles%\MSBuild\Microsoft\VisualStudio\v11.0\WebApplications\Microsoft.WebApplication.targets, С VisualStudioVersion 10.0 этот сценарий будет успешным без выходных данных:)

Обновление: мне удалось использовать этот метод на сервере сборки, на котором установлен только Windows SDK 7.1 (на компьютере нет Visual Studio 2010 и 2012). Но я должен был выполнить следующие шаги, чтобы заставить это работать:

  1. Сделайте Windows SDK 7.1 текущей на компьютере, используя ответ Simmo ( /questions/23079416/pri-zapuske-msbuild-ne-udaetsya-prochitat-sdktoolspath/23079437#23079437)
  2. Установка ключа реестра HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VS7\10.0 в "C:\Program Files\Microsoft Visual Studio 10.0\" (используйте соответствующий путь)
  3. Копирование папки%ProgramFiles%\MSBuild\Microsoft\VisualStudio\v11.0 с компьютера разработчика на сервер сборки

Автор сценария:

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%

Нашел два разных решения, которые работали немного по-другому:

1. Это решение основано на ответе alexanderb [ссылка]. К сожалению, у нас это не сработало - некоторые DLL не были скопированы в OutDir. Мы выяснили, что замена ResolveReferences с Build Цель решает проблему - теперь все необходимые файлы копируются в папку OutDir.

 msbuild / target: Build; _WPPCopyWebApplication / p: Configuration = Release; OutDir = C: \ Tmp \ myApp \ MyApp.csproj 
Недостатком этого решения был тот факт, что OutDir содержал не только файлы для публикации.

2. Первое решение работает хорошо, но не так, как мы ожидали. Мы хотели, чтобы функциональность публикации была такой же, как в Visual Studio IDE - то есть только файлы, которые должны быть опубликованы, будут скопированы в выходной каталог. Как уже упоминалось, первое решение копирует гораздо больше файлов в OutDir - веб-сайт для публикации затем сохраняется в _PublishedWebsites/{ProjectName} вложенная папка. Следующая команда решает эту проблему - только файлы для публикации будут скопированы в нужную папку. Теперь у вас есть каталог, который можно публиковать напрямую - по сравнению с первым решением вы сэкономите место на жестком диске.

 msbuild / target: Build; PipelinePreDeployCopyAllFilesToOneFolder / p: Configuration = Release; _PackageTempDir = C: \ Tmp \ myApp \; AutoParameterizationWebConfigConnectionStrings = false MyApp.csproj 
AutoParameterizationWebConfigConnectionStrings=false Параметр гарантирует, что строки подключения не будут обрабатываться как специальные артефакты и будут сгенерированы правильно - для получения дополнительной информации см. ссылку.

Это моя рабочая партия

публиковать-мой-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%

Обратите внимание, что я установил Visual Studio на сервере, чтобы иметь возможность запускать MsBuild.exe поскольку MsBuild.exe в.Net Framework папки не работают.

Вы должны установить свою среду

  • <Имя веб-сайта>
  • <домен>

и ссылка на мой блог.(извините, пост был корейский)

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

    @ECHO OFF
    :: http://stackru.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
    

Вы можете опубликовать решение с желаемым путем с помощью кода ниже, здесь PublishInDFolder - это имя, у которого есть путь, по которому нам нужно опубликовать (нам нужно создать это на рисунке ниже)

Вы можете создать такой файл публикации

Добавьте ниже 2 строки кода в командный файл (.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

Это мой командный файл

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

Для генерации выходных данных публикации предоставьте еще один параметр. msbuild example.sln /p:publishprofile= имя профиля /p:deployonbuild=true /p:configuration=debug/ или любой

вы можете использовать эту команду для публикации веб-приложений с помощью профилей публикации.

      msbuild SolutionName.sln /p:DeployOnBuild=true /p:PublishProfile=PublishProfileName

В этом образце профиля публикации можно создать ZIP-файл выпуска с номером версии, который находится в файле AssemblyInfo.cs по сетевому пути (создание ZIP-файла и удаление других опубликованных файлов с помощью команды PowerShell необязательно).

       <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
     <PropertyGroup>
    <WebPublishMethod>FileSystem</WebPublishMethod>
    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <SiteUrlToLaunchAfterPublish />
    <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
    <ExcludeApp_Data>False</ExcludeApp_Data>
    <Major>0</Major>
    <Minor>1</Minor>
    <Build>2</Build>
    <Publish>C:\</Publish>
    <publishUrl>$(Publish)</publishUrl>
    <DeleteExistingFiles>True</DeleteExistingFiles>
  </PropertyGroup>
  <Target Name="GetBuildUrl">
    <PropertyGroup>      <In>$([System.IO.File]::ReadAllText('$(MSBuildProjectDirectory)\Properties\AssemblyInfo.cs'))</In>
      <TargetPath>\\NetworkPath\ProjectName</TargetPath>
      <Pattern>^\s*\[assembly: AssemblyVersion\(\D*(\d+)\.(\d+)\.(\d+)\.(\d+)</Pattern>
      <Major>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups[1].Value)</Major>
      <Minor>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups[2].Value)</Minor>
      <Build>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups[3].Value)</Build>
      <Sub>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern), System.Text.RegularExpressions.RegexOptions.Multiline).Groups[4].Value)</Sub>
      <Publish>$(TargetPath)\$(Major).$(Minor).$(Build).$(Sub)\</Publish>
      <publishUrl Condition=" '$(Publish)' != '' ">$(Publish)</publishUrl>
      <publishUrl Condition=" '$(Publish)' == '' and '$(LastUsedBuildConfiguration)'!='' ">$(LastUsedBuildConfiguration)</publishUrl>
    </PropertyGroup>
  </Target>
  <Target Name="BeforeBuild" DependsOnTargets="GetBuildUrl">
    <Message Importance="High" Text="|" />
    <Message Importance="High" Text=" ================================================================================================" />
    <Message Importance="High" Text="    BUILD INFO                                                                                    " />
    <Message Importance="High" Text="    Version [$(Major).$(Minor).$(Build)] found in [$(MSBuildProjectDirectory)\Properties\AssemblyInfo.cs] " />
    <Message Importance="High" Text="    Build will be saved to [$(publishUrl)]                                                        " />
    <Message Importance="High" Text=" =================================================================================================" />
    <Message Importance="High" Text="|" />
  </Target>
  <Target Name="Zip" BeforeTargets="AfterBuild">
    <Exec Command="PowerShell -command Compress-Archive -Path $(Publish) -DestinationPath $(Publish)Release.zip" />
    <Exec Command="PowerShell -command Remove-Item -Recurse -Force $(Publish) -Exclude Release.zip" />
  </Target>
</Project>
Другие вопросы по тегам