Ответ 1
Чтобы работать с файлом решения, MSBuild создает временный файл проекта MSBuild, содержащий только некоторые объекты, такие как Сборка и Очистить. Таким образом, вы не можете вызвать свою настраиваемую цель в файле решения.
Я создал настраиваемую общую цель "RealClean", которая удаляет все файлы в каталоге вывода и "промежуточного вывода". Я поместил его в файл Microsoft.Common.targets. Когда я запускаю MsBuild на моем csproj, все в порядке. Но когда я запускаю MsBuild на моем sln (который просто ссылается на список csproj), у меня есть следующая ошибка
error MSB4057: The target "RealClean" does not exist in the project.
Ниже приведена командная строка для запуска MsBuild
C:\Windows\Microsoft .NET\Framework\v3.5\MsBuild.exe /p:Configuration="Release";OutputPath="..\..\MSBuild.Referentiel.net35";nowarn="1591,1573" /t:RealClean mySolution.sln
Любые подсказки?
Чтобы работать с файлом решения, MSBuild создает временный файл проекта MSBuild, содержащий только некоторые объекты, такие как Сборка и Очистить. Таким образом, вы не можете вызвать свою настраиваемую цель в файле решения.
У меня была такая же проблема, но я не хотел изменять вещи за пределами исходного дерева, чтобы заставить это работать. Добавление файлов в C:\Program Files... означает, что вы должны сделать это вручную на каждом dev-машине, чтобы получить такое же поведение.
Я сделал три вещи:
1) Создал файл пользовательских целей, который я импортирую в каждый проект С# и/или VB/F # в своем решении, добавив в каждый файл proj следующее:
<!-- Rest of project file -->
<PropertyGroup Condition="'$(SolutionDir)' == '' or '$(SolutionDir)' == '*undefined*'">
<!-- Relative path to containing solution folder -->
<SolutionDir>..\</SolutionDir>
</PropertyGroup>
<Import Project="$(SolutionDir)CommonSettings.targets" />
2) Добавлена чистая цель, которая вызывается после реальной очистки (используя атрибут AfterTargets из MSBuild 4.0):
<Target Name="CleanCs" AfterTargets="Clean">
<Message Text="Deep cleaning C# project..." />
<CreateItem Include="$(OutDir)**\*.*; $(ProjectDir)\obj\**\*.*; $(IntermediateOutputPath)**\*.*"
Exclude="**\bin\**\*.vshost.exe; $(IntermediateOutputPath)**\*.log">
<Output TaskParameter="Include" ItemName="AfterClean_FilesToDelete"/>
</CreateItem>
<Delete Files="@(AfterClean_FilesToDelete)" />
<CreateItem Include="$(ProjectDir)\obj\" >
<Output TaskParameter="Include" ItemName="AfterClean_DirectoriesToDelete" />
</CreateItem>
<CreateItem Include ="$(ProjectDir)\bin\" Condition="'$(TargetExt)' != '.exe'" >
<Output TaskParameter="Include" ItemName="AfterClean_DirectoriesToDelete"/>
</CreateItem>
<RemoveDir ContinueOnError="true" Directories="@(AfterClean_DirectoriesToDelete)" />
</Target>
3) В моем проекте MSBuild с непрерывной интеграцией я проверяю и удостоверяюсь, что все файлы proj имеют # 1:
<ItemGroup>
<!-- Exclude viewer acceptance tests as they must compile as x86 -->
<CheckProjects_CsProjects Include="**\*.csproj" />
</ItemGroup>
<Target Name="CheckProjects">
<!--
Look for C# projects that don't import CommonSettingsCs.targets
-->
<XmlRead XPath="//n:Project[count(n:Import[@Project[contains(string(), 'CommonSettingsCs.targets')]]) = 0]/n:PropertyGroup/n:AssemblyName/text() "
XmlFileName="%(CheckProjects_CsProjects.Identity)"
Namespace="http://schemas.microsoft.com/developer/msbuild/2003"
Prefix="n" >
<Output TaskParameter="Value" ItemName="CheckProjects_CsMissingImports"/>
</XmlRead>
<Error Text="Project missing CommonSettingsCs.targets: %(CheckProjects_CsMissingImports.Identity)"
Condition="'%(CheckProjects_CsMissingImports.Identity)' != ''" />
</Target>
Это не позволяет разработчикам забыть добавить # 1. Вы можете создать свой собственный шаблон проекта, чтобы убедиться, что все новые проекты имеют это по умолчанию.
Преимущество такого подхода заключается в том, что для создания нового набора исходного дерева не требуется ничего, кроме получения текущего исходного дерева. Недостатком является то, что вы должны редактировать файлы проекта один раз при их создании.
Madgnome, вероятно, прав. Но я хотел добавить, что вы не должны редактировать файлы Microsoft.common.targets. Если вы это сделаете, вы рискуете иметь другой процесс сборки на этой машине по сравнению с тем, что есть у всех остальных. В вашем случае вы могли бы создать новый файл MSBuild с помощью только цели RealClean и поместить его на C:\Program Files (x86)\MSBuild\v4.0\Custom.After.Microsoft.Common.targets или для 32 бит C:\Program Files\MSBuild\v4.0\Custom.After.Microsoft.Common.targets и, по сути, это будет то же самое, что вставить этот файл внутри Microsoft.Common.targets, за исключением того, что вам не нужно изменять этот файл.