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

标签 msbuild msbuild-wpp

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

This MSDN article说我可以通过指定命令行来完成

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

但我永远无法让它工作 - MSBuild 返回错误,类似“NotInSlnFolder:Rebuild”目标不存在。指定什么目标(构建、重建或清理)并不重要 - 它在任何情况下都不起作用。

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

MSDN 文档不起作用。或者我错过了什么?

最佳答案

注意:此解决方法并未得到 Microsoft 官方支持,因此不能保证它永远有效。

<小时/>

简短回答

在包含 SLN 文件的文件夹中,在 .{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,并且无论环境变量如何,都会保留。通过分析这些文件,您将了解流程的底层细节并查看可用的自定义机会。

在 .Metaproj 文件中使用某些特定于项目的目标执行 MSBuild 后,您会发现特定于项目的目标列表是硬编码的并且仅支持标准目标(构建、重建、清理、编译、发布;注意:发布和 WebPublish 不同)。 MSBuild 3.5 仅生成 Clean、Rebuild 和 Publish 目标以及 仅包含表示“Build”的项目名称的目标。

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

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

/t:MyCompany_MyProduct_Components:Rebuild

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

分析文件{YourSolution}.sln.metaproj.tmp,您会发现在运行时它会尝试从名为之前的文件导入目标。{YourSolution}.sln.targetsafter.{YourSolution}.sln.targets(如果这些文件存在)。这是解决此 MSBuild 限制/错误的关键。

关于MSBuild - 解决方案的特定于项目的目标不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12036112/

相关文章:

msbuild - 如何从外部文件中读取属性值?

visual-studio - 如何取出 .sln- 或 .csprojfile 名称并将它们用作条件?

iis-7 - 通过 MSBuild 在 Web 部署期间设置 ACL

visual-studio-2010 - 错误 : The Target "GatherAllFilesToPublish" does not exist in the project, 但在 v10.5 文件夹中

msbuild - 在自动部署场景中如何通过命令行覆盖 pubxml 设置?

MSBuild 调用错误版本的 csc.exe

C# 孙项目 DLL 未包含在 msbuild 包中

visual-studio-2012 - 从TeamCity发布vs2012解决方案

unit-testing - 构建从单元测试执行开始