MSBuild - 解决方案的项目特定目标不起作用 [英] MSBuild - Project-specific targets for solution does not work

查看:18
本文介绍了MSBuild - 解决方案的项目特定目标不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a solution that has multiple projects in it, including a web application. I want MSBuild to execute "WebPublish" target against the web application project and "default target" for all other projects in the solution.

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

msbuild SlnFolders.sln /t:NotInSlnfolder:Rebuild;NewFolderInSolutionFolder:Clean

但我永远无法让它工作 - MSBuild 返回一个错误,例如NotInSlnFolder:Rebuild"目标不存在.指定什么目标(Build、Rebuild 或 Clean)都没有关系 - 在任何情况下都不起作用.

But I never could make it work - MSBuild return an error, something like "NotInSlnFolder:Rebuild" target does not exist. It does not matter what target to specify, Build, Rebuild or Clean - it does not work in any case.

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

How can I achieve my goal of specifying project-specific targets for a solution?

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

The MSDN documentation does not work. Or have I missed something?

推荐答案

注意:此解决方法不受 Microsoft 官方支持,因此无法保证它会永远有效.

在包含 SLN 文件的文件夹中,创建文件 before.{YourSolution}.sln.targets,其内容如下:(将大括号中的内容替换为您需要的任何内容.)

In folder with the SLN file, create the file before.{YourSolution}.sln.targets, with the following content: (Replace what in curly brackets to whatever you need.)

<?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.WebAppMyCompany.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>

之后就可以执行命令行了:

After that you can execute the command line:

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

<小时>

长答案

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


Long Answer

If you add environment variable MSBUILDEMITSOLUTION, setting its value to 1, MSBuild will not delete temporary files generated for the solution and projects.

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

This will allow you to find {YourSolution}.sln.metaproj and {YourSolution}.sln.metaproj.tmp files generated in the solution folder, which are just standard MSBuild project files.

对于 MSBuild 3.5,生成的文件是 {YourSolution}.sln.cache 并且无论环境变量如何都会保留.通过分析这些文件,您将了解流程的底层细节并查看可用的定制机会.

For MSBuild 3.5, the generated file is {YourSolution}.sln.cache and is retained regardless of environment variables. Analyzing those files, you will understand low-level details of the process and to see the customization opportunities available.

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

After executing MSBuild with some project-specific target in the .Metaproj file you will find out that the list of project-specific targets is hardcoded and only standard targets are supported (Build, Rebuild, Clean, Compile, Publish; note: Publish and WebPublish are not the same). MSBuild 3.5 only generates Clean, Rebuild and Publish targets as well as a target with just the project's name that means "Build".

您还可以看到 NotInSlnfolder:Rebuild 只是一个自动生成目标的名称.实际上,MSBuild 不会解析它,也不关心项目名称和位置.另请注意,自动生成的目标名称使用解决方案文件夹层次结构指定项目名称,如果它在一个中,例如SolFolderSolSubfolderProjectName:Publish.

You also can see that NotInSlnfolder:Rebuild is just a name of an autogenerated target. In reality MSBuild does not parse it and does not care about project names and location. Also note that the autogenerated target names specify the project name with solution folders hierarchy if it's in one, e.g. SolFolderSolSubfolderProjectName:Publish.

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

One more critically important thing you will find: The MSBuild Target Name does not support dots. All dots in project names are replaced with underscores. For example, for a project named MyCompany.MyProduct.Components you will have to specify in the command line:

/t:MyCompany_MyProduct_Components:Rebuild

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

That's why even standard project-specific target Build didn't work - my project name contained dots.

分析文件{YourSolution}.sln.metaproj.tmp,你会发现它在运行时会尝试从名为before.{YourSolution}.sln.targetsafter.{YourSolution}.sln.targets,如果这些文件存在的话.这是解决此 MSBuild 限制/错误的关键.

Analyzing file {YourSolution}.sln.metaproj.tmp, you will find out that at runtime it tries to import targets from file named before.{YourSolution}.sln.targets and after.{YourSolution}.sln.targets, if those files exist. This has a key to the workaround for this MSBuild limitation/bug.

这篇关于MSBuild - 解决方案的项目特定目标不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆