Использование msbuild для выполнения профиля публикации файловой системы


86

У меня есть проект ac # .Net 4.0, созданный с помощью VS2010, и теперь доступ к нему осуществляется с помощью VS2012.

Я пытаюсь опубликовать только необходимые файлы с этого веб-сайта в место назначения (C: \ builds \ MyProject [Files])

Моя файловая структура: ./ProjectRoot/MyProject.csproj ./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml

Я запускаю через MSBuild следующее:

C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ MSBuild.exe ./ProjectRoot/MyProject.csproj / p: DeployOnBuild = true /p:PublishProfile=./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml

Вот xml в FileSystemDebug.pubxml

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <WebPublishMethod>FileSystem</WebPublishMethod>
    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <SiteUrlToLaunchAfterPublish />
    <ExcludeApp_Data>False</ExcludeApp_Data>
    <publishUrl>C:\builds\MyProject\</publishUrl>
    <DeleteExistingFiles>True</DeleteExistingFiles>
  </PropertyGroup>
</Project>

В результате поведение:

  • здесь создается zip-файл: ./ProjectRoot/obj/Debug/Package/MyProject.zip
  • В <publishUrl>C:\builds\MyProject\</publishUrl>WTF ничего не разворачивается
  • Создаваемый zip-файл представляет собой скучный завтрак, полный файлов, которые не нужны приложению.

Когда я запускаю этот профиль публикации через Visual Studio, создается папка в * C: \ builds \ MyProject * и содержит именно те артефакты, которые мне нужны.

Как мне получить этот простой результат из msbuild?

Ответы:


51

К вашему сведению: у меня была такая же проблема с Visual Studio 2015. После многих часов попыток теперь я могу справиться msbuild myproject.csproj /p:DeployOnBuild=true /p:PublishProfile=myprofile.

Мне пришлось отредактировать мой файл .csproj, чтобы он заработал. Он содержал такую ​​строку:

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" 
  Condition="false" />

Я изменил эту строку следующим образом:

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v14.0\WebApplications\Microsoft.WebApplication.targets" />

(Я изменил 10.0 на 14.0, не уверен, было ли это необходимо. Но мне определенно пришлось удалить часть условия.)


1
Условный импорт с Condition="false"существует для обратной совместимости. VS2010 требует, чтобы этот импорт существовал, даже если он пропущен из-за условия ложности. Если вы посмотрите еще раз, то увидите, что csproj содержит еще один импорт, для $(VSToolsPath)\WebApplications\Microsoft.WebApplication.targetsкоторого разрешается файл target для текущей версии Visual Studio.
Стивен Ликенс, 04

3
Обратите внимание на стратегическое использование $(MSBuildToolsVersion)в пути к учетной записи для правильной версии VS: <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(MSBuildToolsVersion)\WebApplications\Microsoft.WebApplication.targets" Condition="false" />. Это сработало для меня в обновлении 1 VS2015
Аль Дасс

42

Нашел ответ здесь: http://www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild

В Visual Studio 2010 есть отличные новые функции публикации проектов веб-приложений, которые позволяют легко публиковать проект веб-приложения одним нажатием кнопки. За кулисами преобразование Web.config и создание пакета выполняется массивным скриптом MSBuild, который импортируется в файл вашего проекта (находится по адресу: C: \ Program Files (x86) \ MSBuild \ Microsoft \ VisualStudio \ v10.0 \ Web \ Microsoft .Web.Publishing.targets). К сожалению, сценарий чрезвычайно сложен, запутан и недокументирован (за исключением некоторых плохо написанных и в основном бесполезных комментариев в файле). Было бы неплохо получить большую блок-схему этого файла и некоторую документацию о том, как подключиться к нему, но, к сожалению, ее не хватает (или, по крайней мере, я не могу ее найти).

К сожалению, это означает, что выполнение публикации через командную строку гораздо более непрозрачно, чем должно быть. Я был удивлен отсутствием документации в этой области, потому что в наши дни многие магазины используют сервер непрерывной интеграции, а некоторые даже выполняют автоматическое развертывание (с чем могут сильно помочь функции публикации VS2010), поэтому я бы подумал, что включение этого ( легко!) было бы основным требованием для этой функции.

В любом случае, после того, как я часами копался в файле Microsoft.Web.Publishing.targets и бился головой о стену проб и ошибок, мне удалось выяснить, как Visual Studio, похоже, выполняет свою магию одним щелчком мыши «Опубликовать в файловой системе» и функции «Сборка пакета развертывания». Я немного расскажу о сценариях MSBuild, поэтому, если вы не знакомы с MSBuild, я предлагаю вам проверить эту страницу MSDN с ускоренным курсом.

Опубликовать в файловой системе

Диалог публикации в файловой системе VS2010 «Публикация в файловой системе» потребовал у меня времени, чтобы разобраться, потому что я ожидал, что будет иметь место какое-то разумное использование MSBuild. Вместо этого VS2010 делает что-то довольно странное: он вызывает MSBuild для выполнения своего рода полуразвертывания, которое подготавливает файлы веб-приложения в папке obj вашего проекта, а затем, похоже, выполняет ручное копирование этих файлов (т. Е. Вне MSBuild) в вашу целевую папку публикации. Это действительно ужасное поведение, потому что MSBuild предназначен для копирования файлов (и других вещей, связанных со сборкой), поэтому было бы разумно, если бы весь процесс был всего лишь одной целью MSBuild, которую вызывала VS2010, а не целью, а затем копией вручную.

Это означает, что сделать это через MSBuild в командной строке не так просто, как вызвать файл проекта с определенной целью и установить некоторые свойства. Вам нужно будет сделать то, что должен был сделать VS2010: самостоятельно создать цель, которая выполняет половину развертывания, а затем копирует результаты в целевую папку. Чтобы отредактировать файл проекта, щелкните правой кнопкой мыши проект в VS2010 и выберите «Выгрузить проект», затем щелкните еще раз правой кнопкой мыши и выберите «Изменить». Прокрутите вниз, пока не найдете элемент Import, который импортирует целевые объекты веб-приложений (Microsoft.WebApplication.targets; сам этот файл импортирует файл Microsoft.Web.Publishing.targets, упомянутый ранее). Под этой строкой мы добавим нашу новую цель под названием PublishToFileSystem:

<Target Name="PublishToFileSystem"
        DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
    <Error Condition="'$(PublishDestination)'==''"
           Text="The PublishDestination property must be set to the intended publishing destination." />
    <MakeDir Condition="!Exists($(PublishDestination))"
             Directories="$(PublishDestination)" />

    <ItemGroup>
        <PublishFiles Include="$(_PackageTempDir)\**\*.*" />
    </ItemGroup>

    <Copy SourceFiles="@(PublishFiles)"
          DestinationFiles="@(PublishFiles->'$(PublishDestination)\%(RecursiveDir)%(Filename)%(Extension)')"
          SkipUnchangedFiles="True" />
</Target>

Эта цель зависит от цели PipelinePreDeployCopyAllFilesToOneFolder, которую VS2010 вызывает перед копированием вручную. Некоторые поиски в Microsoft.Web.Publishing.targets показывают, что при вызове этой цели файлы проекта помещаются в каталог, указанный свойством _PackageTempDir.

Первая задача, которую мы вызываем в нашей цели, - это задача Error, для которой мы поместили условие, гарантирующее, что задача будет выполняться только в том случае, если свойство PublishDestination не было установлено. Это поймает вас и приведет к ошибке сборки, если вы забыли указать свойство PublishDestination. Затем мы вызываем задачу MakeDir для создания этого каталога PublishDestination, если он еще не существует.

Затем мы определяем элемент под названием PublishFiles, который представляет все файлы, находящиеся в папке _PackageTempDir. Затем вызывается задача копирования, которая копирует все эти файлы в папку назначения публикации. Атрибут DestinationFiles в элементе Copy немного сложен; он выполняет преобразование элементов и преобразует их пути в новые пути, основанные на папке PublishDestination (ознакомьтесь с метаданными хорошо известных элементов, чтобы узнать, что означают эти% () s).

Чтобы вызвать эту цель из командной строки, теперь мы можем просто выполнить эту команду (очевидно, изменив имя файла проекта и свойства в соответствии с вашими требованиями):

msbuild Website.csproj "/p:Platform=AnyCPU;Configuration=Release;PublishDestination=F:\Temp\Publish" /t:PublishToFileSystem

3
Я не могу понять фрагмент кода для новой цели (он показывает 01 02 03 ...). Не могли бы вы отредактировать?
fan711

2
Я согласен с fan711. Впрочем, решение описано по ссылке - зачем было тогда его копировать?
Антон Курьян

4
@ АнтонКурьян: Ссылки имеют тенденцию умирать через некоторое время, поэтому вопросы и ответы на stackoverflow.com всегда должны быть автономными, не полагаясь на внешние ресурсы.
Оливер

Результаты выглядят так, как будто профиль публикации вообще не используется MSBuild, а вместо этого выполняет пакет (может быть, по умолчанию?). То, что ваше нижеприведенное решение делает для репликации того, что настроено для профиля, что Microsoft.Web.Publishing.targets обрабатывает, выбирая правильный тип из папки развертывания (для FileSystem). Похоже, вы изобретаете велосипед здесь, вместо того, чтобы решать эту проблему. Но не могу сказать наверняка без журнала MSBuild. Я заставил свой работать, подробности в моем ответе
GregS

1
Решение GregS у меня не работает. Сборки производятся нормально, но файлы в каталог публикации не копируются
спешит

19

По-прежнему возникли проблемы после попытки ответить на все приведенные выше ответы (я использую Visual Studio 2013). В папку публикации ничего не скопировано.

Загвоздка заключалась в том, что если я запускаю MSBuild с отдельным проектом вместо решения, мне нужно добавить дополнительный параметр, указывающий версию Visual Studio:

/p:VisualStudioVersion=12.0

12.0предназначен для VS2013, замените его версией, которую вы используете. Как только я добавил этот параметр, все заработало.

Полная командная строка выглядит так:

MSBuild C:\PathToMyProject\MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=MyPublishProfile /p:VisualStudioVersion=12.0

Я нашел это здесь:

http://www.asp.net/mvc/overview/deployment/visual-studio-web-deployment/command-line-deployment

Они заявляют:

Если вы указываете индивидуальный проект вместо решения, вам нужно добавить параметр, указывающий версию Visual Studio.


12

Мне кажется, что ваш профиль публикации не используется и выполняет некоторую упаковку по умолчанию. Цели Microsoft Web Publish делают все, что вы делаете выше, они выбирают правильные цели на основе конфигурации.

Я заставил свою работать без проблем на этапе TeamCity MSBuild, но я указал явный путь к профилю, вам просто нужно называть его по имени без .pubxml (например, FileSystemDebug). Пока он будет находиться в стандартной папке, которая есть у вас.

Пример:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ./ProjectRoot/MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=FileSystemDebug

Обратите внимание, что это было сделано с использованием версий Visual Studio 2012 целевых объектов Microsoft Web Publish, обычно расположенных в «C: \ Program Files (x86) \ MSBuild \ Microsoft \ VisualStudio \ v11.0 \ Web». Ознакомьтесь с папкой развертывания для конкретных используемых типов развертывания.


MS внесла много улучшений с тех пор, как это было опубликовано несколько лет назад, спасибо за обновленное программирование?
П. Роу

3

К вашему сведению: та же проблема с запуском на сервере сборки (Jenkins с установленным msbuild 15, управляемый из VS 2017 в веб-проекте .NET Core 2.1).

В моем случае это было использование цели "publish" с msbuild, которая игнорировала профиль.

Итак, моя команда msbuild началась с:

msbuild /t:restore;build;publish

Это правильно запустило процесс публикации, но никакая комбинация или вариант «/ p: PublishProfile = FolderProfile» никогда не помогала выбрать профиль, который я хотел использовать («FolderProfile»).

Когда я перестал использовать цель публикации:

msbuild /t:restore;build /p:DeployOnBuild=true /p:PublishProfile=FolderProfile

Я (по глупости) думал, что это не будет иметь никакого значения, но как только я использовал переключатель DeployOnBuild, он правильно поднял профиль.


3

На самом деле я объединил все ваши ответы в свое собственное решение, как решить указанную выше проблему:

  1. Я создаю файл pubxml в соответствии со своими потребностями
  2. Затем я копирую все параметры из файла pubxml в свой собственный список параметров «/ p: foo = bar» для msbuild.exe.
  3. Выкидываю файл pubxml

Результат такой:

msbuild /t:restore /t:build /p:WebPublishMethod=FileSystem /p:publishUrl=C:\builds\MyProject\ /p:DeleteExistingFiles=True /p:LastUsedPlatform="Any CPU" /p:Configuration=Release


1

Сначала проверьте версию Visual Studio на компьютере разработчика, на котором можно опубликовать решение (проект). как показано для VS 2013

 /p:VisualStudioVersion=12.0

добавьте указанную выше командную строку, чтобы указать, какая версия Visual Studio должна создавать проект. Как и в предыдущих ответах, это может произойти, когда мы пытаемся опубликовать только один проект, а не все решение.

Итак, полный код будет примерно таким

"C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ msbuild.exe" "C: \ Program Files (x86) \ Jenkins \ workspace \ Jenkinssecondsample \ MVCSampleJenkins \ MVCSampleJenkins.csproj" / T: Build; Package / p : Configuration = DEBUG / p: OutputPath = "obj \ DEBUG" / p: DeployIisAppPath = "Веб-сайт по умолчанию / jenkinsdemoapp" /p:VisualStudioVersion=12.0


1
Извините, шаммакалубо, вы сильно неверно истолковали вопрос.
P. Roe

1
@shammakalubo Ответ правильный, но он не изложен полностью. Этот параметр необходимо добавить к команде, упомянутой OP, которая затем станет: MSBuild C:\PathToMyProject\MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=MyPublishProfile /p:VisualStudioVersion=12.0Этот параметр - это то, что мне не хватало, и я решил мою проблему. Вам просто нужно полностью указать ответ!
Сайед Вакас

@WaqasShah Спасибо, как вы упомянули, я отредактировал свой ответ и опубликовал полный код, как он будет выглядеть.
Шамми
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.