MSBuild - Проектные цели для решения не работают

У меня есть решение с несколькими проектами, включая веб-приложение. Я хочу, чтобы MSBuild выполнял цель "WebPublish" для проекта веб-приложения и "цель по умолчанию" для всех других проектов в решении.

В этой статье MSDN говорится, что я могу сделать это, указав командную строку

msbuild SlnFolders.sln /t:NotInSlnfolder:Rebuild;NewFolder\InSolutionFolder:Clean

Но я никогда не мог заставить это работать - MSBuild возвращает ошибку, что-то вроде цели "NotInSlnFolder:Rebuild" не существует. Неважно, какую цель указать, Build, Rebuild или Clean - это не работает ни в коем случае.

Как я могу достичь своей цели, указав конкретные цели проекта для решения?

Документация MSDN не работает. Или я что-то пропустил?

2 ответа

Решение

ПРИМЕЧАНИЕ. Этот обходной путь официально не поддерживается корпорацией Microsoft, поэтому нет гарантии, что он будет работать вечно.


Короткий ответ

В папке с файлом SLN создайте файл before.{YourSolution}.sln.targetsсо следующим содержанием: (замените то, что в фигурных скобках, на все, что вам нужно.)

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="{MyCompany_MyProduct_WebApp:WebPublish}">
    <MSBuild
        Condition="'%(ProjectReference.Identity)' == '{$(SolutionDir)MyCompany.MyProduct.WebApp\MyCompany.MyProduct.WebApp.csproj}'"
        Projects="@(ProjectReference)"
        Targets="{WebPublish}"
        BuildInParallel="True"
        ToolsVersion="4.0"
        Properties="BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)"
        SkipNonexistentProjects="%(ProjectReference.SkipNonexistentProjects)" />
  </Target>
</Project>

После этого вы можете выполнить командную строку:

msbuild {YourSolution}.sln /t:{MyCompany_MyProduct_WebApp:WebPublish}

Длинный ответ

Если вы добавите переменную среды MSBUILDEMITSOLUTIONПри значении 1 MSBuild не будет удалять временные файлы, созданные для решения и проектов.

Это позволит вам найти {YourSolution}.sln.metaproj а также {YourSolution}.sln.metaproj.tmp файлы, сгенерированные в папке решения, которые являются просто стандартными файлами проекта MSBuild.

Для MSBuild 3.5 сгенерированный файл {YourSolution}.sln.cache и сохраняется независимо от переменных среды. Анализируя эти файлы, вы поймете низкоуровневые детали процесса и увидите доступные возможности настройки.

После выполнения MSBuild с определенной целью проекта в файле.Metaproj вы обнаружите, что список целей проекта жестко закодирован и поддерживаются только стандартные цели (Build, Rebuild, Clean, Compile, Publish; примечание: Publish и WebPublish не то же самое). MSBuild 3.5 генерирует только цели "Очистить", "Перестроить" и "Опубликовать", а также цель только с именем проекта, что означает "Сборка".

Вы также можете увидеть, что NotInSlnfolder:Rebuild это просто имя автоматически сгенерированной цели. На самом деле MSBuild не разбирает его и не заботится об именах и местоположении проекта. Также обратите внимание, что автоматически генерируемые целевые имена указывают имя проекта с иерархией папок решения, если оно в одной, например SolFolder\SolSubfolder\ProjectName:Publish,

Еще одна критически важная вещь, которую вы найдете: имя цели MSBuild не поддерживает точки. Все точки в названиях проектов заменены подчеркиванием. Например, для проекта с именем MyCompany.MyProduct.Components вам нужно будет указать в командной строке:

/t:MyCompany_MyProduct_Components:Rebuild

Вот почему даже стандартная целевая сборка проекта не работала - в моем названии проекта были точки.

Анализ файла {YourSolution}.sln.metaproj.tmp, вы обнаружите, что во время выполнения он пытается импортировать цели из файла с именем before.{YourSolution}.sln.targets а также after.{YourSolution}.sln.targets, если эти файлы существуют. Это имеет ключ к обходу этого ограничения / ошибки MSBuild.

Вы можете открыть файл решения в текстовом редакторе и проверить, существует ли следующая строка или нет, если нет, то вы можете добавить

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> внутри <Project> тег.

Надеюсь, это поможет вам.

Другие вопросы по тегам