MSBuild 条件

MSBuild 支持可在允许 Condition 属性的任何位置应用的特定条件集;请参阅 支持的元素。 下表说明了这些条件。

条件 描述
'stringA' == 'stringB' 如果 stringA 等于 stringB,则计算结果为 true

例如:

Condition="'$(Configuration)'=='DEBUG'"

简单字母数字字符串或布尔值不需要单引号。 但是,空值需要单引号。 此检查不区分大小写。
'stringA' != 'stringB' 如果 stringA 不等于 stringB,则计算结果为 true

例如:

Condition="'$(Configuration)'!='DEBUG'"

简单字母数字字符串或布尔值不需要单引号。 但是,空值需要单引号。 此检查不区分大小写。
<、>、<=、>= 计算操作数的数值。 如果关系评估为 true,则返回 true。 操作数的计算结果必须为十进制或十六进制数或四部分虚线版本。 十六进制数字必须以 0x开头。 注意: 在 XML 中,必须转义字符 <>。 符号 < 表示为 &lt;。 符号 > 表示为 &gt;
Exists(“stringA”) 如果存在名称 stringA 的文件或文件夹,则计算结果为 true

例如:

Condition="!Exists('$(Folder)')"

简单字母数字字符串或布尔值不需要单引号。 但是,空值需要单引号。 此条件不会扩展通配符,如 *
HasTrailingSlash('stringA') 如果指定的字符串包含尾部后斜杠 (\) 或正斜杠 (/) 字符,则计算结果为 true

例如:

Condition="!HasTrailingSlash('$(OutputPath)')"

简单字母数字字符串或布尔值不需要单引号。 但是,空值需要单引号。
! 如果操作数的计算结果为 false,则计算结果为 true
And 如果两个操作数的计算结果为 true,则计算结果为 true
Or 如果至少有一个操作数的计算结果为 true,则计算结果为 true
() 计算结果为 true 的分组机制(如果表达式包含在计算结果中为 true)。
$if$ ( %expression% ), $else$, $endif$ 检查指定的 %expression% 是否与传递的自定义模板参数的字符串值匹配。 如果 $if$ 条件的计算结果为 true,则运行其语句;否则,将检查 $else$ 条件。 如果 $else$ 条件 true,则运行其语句;否则,$endif$ 条件将结束表达式计算。

有关用法示例,请参阅 Visual Studio 项目/项模板参数逻辑

Condition 元素是单个字符串,因此表达式中使用的任何字符串(包括属性值周围)都需要用单引号括起来。 允许运算符之间的空格,通常用于可读性,但它们不是必需的。

若要使用布尔 AndOr 运算符,请在 Condition 元素的字符串值中指定操作数,如以下示例所示:

Condition="'$(Configuration)' == 'Debug' And '$(MSBuildProjectExtension)' == '.csproj'"

可以链接布尔运算符。 运算符 And 优先级高于 Or,但为了清楚起见,我们建议在使用多个布尔运算符时使用括号来明确计算顺序。 否则,MSBuild 会发出警告MSB4130。

可以在条件中使用字符串方法,如以下示例所示,其中 TrimEnd() 函数仅用于比较字符串的相关部分,以区分 .NET Framework 和 .NET Core 目标框架。

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFrameworks>net45;net48;netstandard2.1;netcoreapp2.1;netcoreapp3.1</TargetFrameworks>
    </PropertyGroup>

    <PropertyGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
        <!-- Properties for .NET Framework -->
    </PropertyGroup>

</Project>

在 MSBuild 项目文件中,没有真正的布尔类型。 布尔数据以可能为空或设置为任何值的属性表示。 因此,'$(Prop)' == 'true' 表示“如果 Prop 是 true”,但 '$(Prop)' != 'false' 表示“如果 Prop 是 true 或未设置或设置为其他内容”。

布尔逻辑仅在条件上下文中计算,因此属性设置(如 <Prop2>'$(Prop1)' == 'true'</Prop>)表示为字符串(在变量扩展后),不计算为布尔值。

MSBuild 实现一些特殊的处理规则,以便更轻松地使用用作布尔值的字符串属性。 接受布尔文本,因此 Condition="true"Condition="false" 按预期工作。 MSBuild 还包含用于支持布尔求反运算符的特殊规则。 因此,如果 $(Prop) 为“true”,则 !$(Prop) 扩展为 !true,并且此值与 false进行比较,如预期的那样。

比较版本

关系运算符 <><=>= 支持由 System.Version分析的版本,以便可以比较具有四个数值部分的版本。 例如,'1.2.3.4' < '1.10.0.0'true

谨慎

当一个或两个版本未指定所有四个部分时,System.Version 比较可能会产生令人惊讶的结果。 例如,版本 1.1 早于版本 1.1.0。

MSBuild 提供 属性函数来比较具有与语义版本控制(semver)兼容的不同规则集的版本

条件中的扩展

根据项目文件中的位置,可以对属性($)、项列表(@)和项元数据(%)使用扩展。 扩展取决于 MSBuild 如何处理项目文件

性能

计算并转换为属性值,其中包含表达式(如 $(SomeProperty))的条件。 如果条件不在目标之外,则表达式将在项目文件的计算过程中计算。 属性的值取决于展开所有导入后项目文件中的位置。 如果条件位于目标中,则当目标执行时会对其进行评估,并且该值受执行生成期间发生的任何更改的影响。

在展开的项目文件中未定义的属性,其中条件表达式的计算结果为空字符串,没有任何诊断错误或警告。

项列表

包含 @-expression(如 @(SomeItems))的条件在顶级和目标的项目组中展开。

项可以依赖于任何属性,并且可以依赖于已按顺序定义的项。

原因是 MSBuild 在多个传递中处理项目文件。 项评估传递在初始属性计算和导入扩展传递之后发生。 因此,在开始定义项后计算的任何条件中,都允许 @-expression。 也就是说,在项、项组和目标中。

元数据

包含元数据表达式(如 %(ItemMetadata))的条件在与项列表相同的上下文中展开,即顶级和目标项组中的项组中。 但是,扩展在项组中可能有不同的行为,具体取决于项组是位于目标外部还是目标内部。 此外,对于各种形式的元数据表达式,%(ItemName.MetadataName)%(JustTheMetadataName)@(ItemName->'%(MetadataName)'),仅允许项转换(最后一个)在目标之外。 目标中的 %-expression 的值在运行时计算,具体取决于目标执行期间的任何状态更改。 目标的执行及其中包含的任何 %表达式的值也取决于目标的批处理,还可以触发批处理;请参阅 MSBuild 批处理

支持的元素

以下元素支持 Condition 属性:

  • 进口
  • ImportGroup
  • 项目
  • ItemDefinitionGroup
  • ItemGroup
  • ItemMetadata
  • OnError
  • 输出
  • 财产
  • PropertyGroup
  • 目标
  • 任务
  • UsingTask
  • 什么时候

另请参阅