如何从相应的 csproj 文件中忽略命令行上给出的属性值?

mar*_*ark 4 msbuild

我们的 TFS 构建控制器将同一解决方案中的所有项目构建到同一个共享 bin 目录中,因为 TFS 构建工作流通过 OutDir参数给负责构建解决方案的 msbuild 命令。

我有一个项目,我想抑制这种行为并让它构建到标准的相对bin\Debugbin\Release目录中。

但我找不到如何去做。实际上,请观察以下简单的 msbuild 脚本:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <OutDir>$(MSBuildThisFileDirectory)bin\$(Configuration)</OutDir>
  </PropertyGroup>
  <Target Name="Build">
      <Message Text="$(OutDir)" Importance="High"/>
  </Target>
</Project>
Run Code Online (Sandbox Code Playgroud)

现在,我正在运行它:

PS C:\> msbuild .\1.csproj /p:OutDir=XoXo /nologo
Build started 11/13/2015 9:50:57 PM.
Project "C:\1.csproj" on node 1 (default targets).
Build:
  XoXo
Done Building Project "C:\1.csproj" (default targets).


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

Time Elapsed 00:00:00.03
PS C:\>
Run Code Online (Sandbox Code Playgroud)

注意它显示XoXo,忽略我从内部覆盖它的尝试。

那么,有可能吗?

sti*_*ijn 5

这有点经典的 RTFM 情况,但仍然很有趣。请参阅MSBuild 属性的文档,特别是有关全局属性的部分以及如何使属性不被前者覆盖:

MSBuild 允许您使用 /property(或 /p)开关在命令行上设置属性。这些全局属性值会覆盖在项目文件中设置的属性值。这包括环境属性,但不包括无法更改的保留属性。

还可以使用 MSBuild 任务的 Properties 属性为多项目构建中的子项目设置或修改全局属性

如果您在项目标记中使用TreatAsLocalProperty特性指定属性,则该全局属性值不会覆盖在项目文件中设置的属性值。

它还链接到项目元素文档,该文档基本上重复了相同的信息,并表示属性中的多个属性应该用分号分隔。

简而言之,代码适用于您的案例:

<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
         TreatAsLocalProperty="OutDir">
Run Code Online (Sandbox Code Playgroud)

请注意,这将完全禁止从项目外部更改 OutDir。更可配置的替代解决方案可能是拥有一个小型存根项目,您可以使用它来构建 TFS 而不是主项目。在该项目中,您可以决定是将 OutDir 传递给实际项目还是覆盖它,例如通过导入可能已定义或未定义的文件或基于环境变量等来获取值。这给出了基本思想:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- Try import if this file exists, it should supply the value for CustomOutDir-->
  <Import Project="$(MSBuildThisFileDirectory)customoutdir.props" Condition="Exists('$(MSBuildThisFileDirectory)customoutdir.props')"/>
  <PropertyGroup>
    <!-- Default value for CustomOutDir if not set elsewhere -->
    <CustomOutDir Condition="'$(CustomOutDir)' == ''">$(MSBuildThisFileDirectory)bin\$(Configuration)</CustomOutDir>
    <!-- ApplyCustomOutDir specifies whether or not to apply CustomOutDir -->
    <ActualOutDir Condition="'$(ApplyCustomOutDir)' == 'True'">$(CustomOutDir)</ActualOutDir>
    <ActualOutDir Condition="'$(ApplyCustomOutDir)' != 'True'">$(OutDir)</ActualOutDir>
  </PropertyGroup>
  <Target Name="Build">
    <MSBuild Projects="$(MasterProject)" Properties="OutDir=$(ActualOutDir)"/>
  </Target>
</Project>
Run Code Online (Sandbox Code Playgroud)

并且应该通过传递neede属性来调用

msbuild stub.targets /p:MasterProject=/path/to/main.vcxproj;ApplyCustomOutDir=True
Run Code Online (Sandbox Code Playgroud)

(我从未使用过 TFS,因此获取属性的方式可能会有所不同)