【问题标题】:Overriding MSBuildExtensionsPath in the MSBuild task is flaky在 MSBuild 任务中覆盖 MSBuildExtensionsPath 很不稳定
【发布时间】:2010-05-20 18:44:53
【问题描述】:

这已在 MS Connect 上交叉发布:

https://connect.microsoft.com/VisualStudio/feedback/details/560451

在通过 msbuild 构建包含 C# Web 应用程序项目的解决方案时,我试图覆盖属性 $(MSBuildExtensionsPath)。我这样做是因为 Web 应用程序 csproj 文件导入文件“$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets”。此文件由 Visual Studio 安装到标准 $(MSBuildExtensionsPath) 位置 (C:\Program Files\MSBuild)。我想消除对安装在机器上的这个文件的依赖(我想让我的构建服务器尽可能“干净”)。为了做到这一点,我想将 Microsoft.WebApplication.targets 包含在我的项目的源代码控制中,然后覆盖 $(MSBuildExtensionsPath),以便 csproj 将导入此包含的 Microsoft.WebApplication.targets 版本。这种方法允许我删除依赖项,而无需我手动修改 Web 应用程序 csproj 文件。

当我从命令行构建解决方案文件时,此方案运行良好,通过 /p 标志在命令行向 msbuild 提供 $(MSBuildExtensionsPath) 的自定义值。但是,如果我尝试使用自定义 msbuild 项目文件中的 MSBuild 任务构建解决方案(使用“Properties”属性覆盖 MSBuildExtensionsPath),则会失败,因为 Web 应用程序 csproj 文件正在尝试从“标准”Microsoft.WebApplication.targets 位置(C:\Program Files\MSBuild)。值得注意的是,如果我使用自定义项目文件中的“Exec”任务运行 msbuild,它就可以工作。更值得注意的是,在我使用“EXEC”任务(或直接从命令行)运行构建之后,我第一次使用“MSBuild”任务运行构建,构建工作。

以前有人见过这样的行为吗?我疯了吗?是否有人知道此问题的根本原因、可能的解决方法,或者这是否是 MSBuild 中的合法错误?

复制步骤:

1) 在 MSVS 2008 (Fake.sln) 中创建一个新的空解决方案

2) 将新的 C# Web 应用程序添加到解决方案 (WebApplication1.csproj)

3) 关闭 MSVS

4) 将“C:\Program Files\MSBuild\”的内容复制到包含您的解决方案的目录中名为“MSBuildExtensions”的目录中。

5) 重命名目录“C:\Program Files\MSBuild\Microsoft\VisualStudio\v9.0\WebApplications”,这样 WebApplication1.csproj 将无法从该位置导入 Microsoft.WebApplication.targets。

6) 在与解决方案相同的目录中创建一个名为“TestBuild.proj”的自定义 MSBuild 项目文件。它应该有以下内容:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="BuildMSBuild">

<PropertyGroup>
    <MSBuildExtensionsPath>$(MSBuildProjectDirectory)\MSBuildExtensions\</MSBuildExtensionsPath>
    <BuildThis>Fake.sln</BuildThis>
</PropertyGroup>

<Target Name="BuildMSBuild">
    <MSBuild Projects="$(BuildThis)" Properties="MSBuildExtensionsPath=$(MSBuildExtensionsPath);" Targets="Clean" />
    <MSBuild Projects="$(BuildThis)" Properties="MSBuildExtensionsPath=$(MSBuildExtensionsPath);"/>
</Target>

</Project>

7) 在 MSVS 命令提示符下执行“msbuild TestBuild.proj”(注意:第一次构建可能会成功,但如果多次运行则会失败)

【问题讨论】:

  • 能否发布您的自定义 msbuild 项目文件,看看出了什么问题。
  • 向问题添加了复制说明。谢谢!
  • 无法在我的机器上复制。注意:如果您的项目是在 64 位机器上创建的,则该属性被命名为:MSBuildExtensionsPath32 并且像 MSBuildExtensionsPath 一样工作
  • 好的,我重现了 MSBuild 3.5 的问题。它适用于 MSBuild 4。
  • 好的,感谢您的帮助 - 很高兴您能重现此内容。由于它已在 .NET 4 中修复,因此我可以坚持使用解决方法,直到我们升级为止。我可以在安装了 VS 的机器上运行这些构建,这样“Microsoft.WebApplication.targets”就会出现在它的预期位置。谢谢!

标签: msbuild msbuild-task


【解决方案1】:

您是否尝试在 CMD 提示符中设置环境变量 MSBuildExtensionPath 然后运行您的构建?

例如:

C:\> SET MSBuildExtensionsPath=C:\My\MSBuild\Extensons

然后在这个项目文件上:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="Build">
    <Message Text='MSBuildExtensionsPath="$(MSBuildExtensionsPath)"' />
  </Target>
</Project>

你会得到以下输出:

c:\Users\chuckeng\Desktop\ConsoleApplication1>"C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe" my.proj
Microsoft (R) Build Engine Version 3.5.30729.4926
[Microsoft .NET Framework, Version 2.0.50727.4927]
Copyright (C) Microsoft Corporation 2007. All rights reserved.

Build started 6/25/2010 1:04:05 PM.
Project "c:\my.proj" on node 0 (default targets).
  MSBuildExtensionsPath="C:\My\MSBuild\Extensons"
Done Building Project "c:\my.proj" (default targets).


Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.03

这也适用于 v4.0。虽然,在 v4.0 中对此类事情的支持通常更好。而且,v4.0 是 100% 向后兼容的(无法承受错误)。因此,您可以使用 v4.0 构建您的 v3.5 和以前的项目。只需选择 ToolsVersion 3.5。

msbuild my.proj /tv:3.5

希望这会有所帮助...

查克英格兰 视觉工作室 项目经理 - MSBuild

【讨论】:

    【解决方案2】:

    这是 MSBuild 3.5 中的错误,但在 MSBuild 4 中已修复。

    如果可以,请切换到 MSBuild 4(您仍然可以编译 3.5 项目),否则您必须在项目文件中使用 override the property

    【讨论】:

      【解决方案3】:

      如果您直接在 Web 应用程序 .csproj 文件中覆盖 MSBuildExtensionsPath,它会正常工作。

      <PropertyGroup>
        <MSBuildExtensionsPath>C:\Users\madgnome\Desktop\msbuild</MSBuildExtensionsPath>
      
        <!-- It works too with relative path -->
        <!--<MSBuildExtensionsPath>..\msbuild</MSBuildExtensionsPath>-->
      </PropertyGroup>
      
      <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
      <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
      

      【讨论】:

      • 是的,没错——我已经试过了。很抱歉没有在帖子中提及。我宁愿不必修改实际的 csproj 文件,因为我希望我的构建系统能够与 Visual Studio 创建的“默认”项目正常工作,而且我不想处理 Visual Studio 对我大喊大叫的问题(或其他开发人员)打开此“修改后的”csproj 文件时。
      【解决方案4】:

      不知道这是否会在未来对任何人有所帮助,但我可以在文件顶部使用以下内容,并且它在 32 位和 64 位构建环境中都能正常工作。

      <PropertyGroup>
        <MSBuildExtensionsPath Condition=" '$(MSBuildExtensionsPath64)' != '' ">$(MSBuildExtensionsPath64)</MSBuildExtensionsPath>
      </PropertyGroup>
      <Import Project="$(MSBuildExtensionsPath)\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks"/>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多