在MSBuild任务中覆盖MSBuildExtensionsPath是不稳定的

时间:2010-05-20 18:44:53

标签: msbuild msbuild-task

这已在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任务构建解决方案(使用“属性”属性覆盖MSBuildExtensionsPath),则会失败,因为Web应用程序csproj文件正在尝试从中导入Microsoft.WebApplication.targets “标准”Microsoft.WebApplication.targets位置(C:\ Program Files \ MSBuild)。值得注意的是,如果我在自定义项目文件中使用“Exec”任务运行msbuild,它就可以运行。更值得注意的是,第一次使用“MSBuild”任务运行构建后,我使用“EXEC”任务(或直接从命令行)运行构建,构建工作。

之前有没有人见过这样的行为?我疯了吗?是否有人知道此问题的根本原因,可能的解决方法,或者这是否是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”(注意:构建可能会在第一次成功,但如果您运行多次则会失败)

4 个答案:

答案 0 :(得分:4)

您是否尝试在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

答案 1 :(得分:3)

如果您直接在网络应用MSBuildExtensionsPath文件中覆盖.csproj,该工作正常。

<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" />

答案 2 :(得分:3)

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

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

答案 3 :(得分:1)

不知道这可能会对将来的任何人有所帮助,但我能够在我的文件顶部使用以下内容,它可以在32位和64位构建环境中运行。

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