Використання msbuild для запуску профілю публікації файлової системи


86

У мене є проект AC # .Net 4.0, створений за допомогою VS2010 і зараз доступний до VS2012.

Я намагаюся опублікувати лише потрібні файли з цього веб-сайту в місці призначення (C: \ builds \ MyProject [Файли])

Моя файлова структура: ./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.

Ось 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

FYI: У мене була та сама проблема з 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який вирішується до цільового файлу для поточної версії Visual Studio.
Steven Liekens

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

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 та натисніть Вивантажити проект, потім ще раз клацніть правою кнопкою миші та натисніть Редагувати. Прокрутіть вниз, поки не знайдете елемент Імпорт, який імпортує цілі веб-додатків (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.

Перше завдання, яке ми викликаємо в нашій цілі, - це завдання Помилка, перед яким ми поставили умову, яка гарантує, що завдання виконується лише в тому випадку, якщо властивість 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 для мене не працює. Збірка чудова, але жоден файл не копіюється в каталог публікацій
rushinge

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 зробила багато вдосконалень, оскільки це було опубліковано кілька років тому, дякую за оновлене програмування?
P. Roe

3

FYI: така сама проблема із запуском на сервері збірки (Дженкінс із встановленим msbuild 15, керований з VS 2017 у веб-проекті .NET Core 2.1).

У моєму випадку саме використання цілі "опублікувати" з 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

додайте наведений вище командний рядок, щоб вказати, яка версія візуальної студії повинна будувати проект. Як і попередні відповіді, це може статися, коли ми намагаємось опублікувати лише один проект, а не ціле рішення.

Отже, повний код буде приблизно таким

"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
Вибачте shammakalubo, що ви дуже неправильно витлумачили питання.
P. Roe

1
@shammakalubo Відповідь правильна, але вона просто не зазначена повністю. Цей параметр потрібно додати до команди, згаданої в OP, яка потім стане: MSBuild C:\PathToMyProject\MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=MyPublishProfile /p:VisualStudioVersion=12.0Цей параметр - це те, чого мені не вистачало та виправило мою проблему. Вам просто потрібно повністю згадати відповідь!
Syed Waqas

@WaqasShah Дякую, як ви вже згадали, я відредагував свою відповідь та опублікував повний код, як би це виглядало.
Shammie,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.