MSBuild - 解决方案的项目特定目标不起作用

Phi*_*nin 26 msbuild msbuild-wpp

我有一个包含多个项目的解决方案,包括一个Web应用程序.我希望MSBuild针对Web应用程序项目执行"WebPublish"目标,并为解决方案中的所有其他项目执行"默认目标".

这篇MSDN文章说我可以指定命令行

msbuild SlnFolders.sln /t:NotInSlnfolder:Rebuild;NewFolder\InSolutionFolder:Clean
Run Code Online (Sandbox Code Playgroud)

但我永远无法使其工作 - MSBuild返回错误,类似"NotInSlnFolder:Rebuild"目标不存在.指定,构建,重建或清理的目标无关紧要 - 它在任何情况下都不起作用.

如何实现为解决方案指定项目特定目标的目标?

MSDN文档不起作用.还是我错过了什么?

Phi*_*nin 40

注意: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>
Run Code Online (Sandbox Code Playgroud)

之后,您可以执行命令行:

msbuild {YourSolution}.sln /t:{MyCompany_MyProduct_WebApp:WebPublish}
Run Code Online (Sandbox Code Playgroud)

答案很长

如果添加环境变量 MSBUILDEMITSOLUTION,将其值设置为1,MSBuild将不会删除为解决方案和项目生成的临时文件.

这将允许您查找解决方案文件夹中生成的文件{YourSolution}.sln.metaproj{YourSolution}.sln.metaproj.tmp文件,这些文件只是标准的MSBuild项目文件.

对于MSBuild 3.5,{YourSolution}.sln.cache无论环境变量如何,都会保留生成的文件.通过分析这些文件,您将了解流程的低级详细信息并查看可用的自定义机会.

在.Metaproj文件中执行带有一些项目特定目标的MSBuild后,您会发现项目特定目标列表是硬编码的,只支持标准目标(构建,重建,清理,编译,发布;注意:发布和WebPublish不一样).MSBuild 3.5仅生成清除,重建和发布目标以及仅具有项目名称(意味着"构建")的目标.

你也可以看到NotInSlnfolder:Rebuild只是一个自动生成目标的名称.实际上,MSBuild不解析它,也不关心项目名称和位置.另请注意,自动生成的目标名称指定具有解决方案文件夹层次结构的项目名称(如果它在一个中),例如SolFolder\SolSubfolder\ProjectName:Publish.

您会发现另一个非常重要的事情:MSBuild目标名称不支持点.项目名称中的所有点都用下划线替换.例如,对于名为的项目,MyCompany.MyProduct.Components您必须在命令行中指定:

/t:MyCompany_MyProduct_Components:Rebuild
Run Code Online (Sandbox Code Playgroud)

这就是为什么即使是标准的项目特定目标Build也不起作用 - 我的项目名称包含.

分析文件{YourSolution}.sln.metaproj.tmp,你会发现,在运行时,它会尝试从指定的文件中导入的目标before.{YourSolution}.sln.targetsafter.{YourSolution}.sln.targets,如果存在这些文件.这有关于此MSBuild限制/错误的解决方法的关键.