MSBuild 属性

属性是可用于配置生成的名称/值对。 属性可用于将值传递到任务、评估条件和存储将在整个项目文件中引用的值。

在项目文件中定义和引用属性

属性的声明方式是:创建一个与属性同名的元素作为 PropertyGroup 元素的子元素。 例如,下面的 XML 将创建一个名为 的值的属性

<PropertyGroup>
    <BuildDir>Build</BuildDir>
</PropertyGroup>

有效的属性名称以大写或小写字母或下划线开头(_);有效的后续字符包括字母数字字符(字母或数字)、下划线和连字符(-)。

在整个项目文件中,使用语法 $(<PropertyName>)引用属性。 例如,使用 引用 上一示例中的属性。

可以通过重新定义属性来更改属性值。 BuildDir可以使用此 XML 为该属性提供一个新值:

<PropertyGroup>
    <BuildDir>Alternate</BuildDir>
</PropertyGroup>

属性按项目文件中显示的顺序进行评估。 分配旧值后,必须声明其新值 BuildDir

保留属性

MSBuild 保留一些属性名称来存储有关项目文件和 MSBuild 二进制文件的信息。 这些属性是使用 $ 表示法引用的,就像任何其他属性一样。 例如,$(MSBuildProjectFile)返回项目文件的完整文件名,包括文件扩展名。

有关详细信息,请参阅如何:引用项目文件的名称或位置MSBuild 保留和常见属性

MSBuild 内部属性

标准导入文件中定义的属性以下划线 (_) 开头是 MSBuild 的私有属性,不应在用户代码中读取、重置或重写。

环境属性

可以引用项目文件中的环境变量,就像引用保留属性一样。 例如,若要在项目文件中使用 PATH 环境变量,请使用 $(Path)。 如果项目包含与环境属性同名的属性定义,则项目中的属性将替代环境变量的值。

每个 MSBuild 项目都有一个独立的环境块:它只看到对其自己的块的读取和写入。 在评估或生成项目文件之前,MSBuild 仅在初始化属性集合时读取环境变量。 之后,环境属性是静态的,也就是说,每个生成工具都以相同的名称和值开头。

若要从生成工具中获取环境变量的当前值,请使用 Property Functions System.Environment.GetEnvironmentVariable。 但是,首选方法是使用任务参数 EnvironmentVariables。 此字符串数组中设置的环境属性可以传递给生成工具,而不会影响系统环境变量。

小窍门

并非所有环境变量都会被读取为初始属性。 忽略其名称不是有效的 MSBuild 属性名称(如“386”)的任何环境变量。

有关详细信息,请参阅 如何:在生成中使用环境变量。

注册表属性

可以使用以下语法读取系统注册表值,其中 Hive 注册表配置单元(例如 ,HKEY_LOCAL_MACHINE), MyKey 是键名称, MySubKey 是子项名称,是 Value 子项的值。

$(registry:Hive\MyKey\MySubKey@Value)

若要获取默认子项值,请省略 。Value

$(registry:Hive\MyKey\MySubKey)

此注册表值可用于初始化生成属性。 例如,若要创建表示 Visual Studio Web 浏览器主页的生成属性,请使用以下代码:

<PropertyGroup>
  <VisualStudioWebBrowserHomePage>
    $(registry:HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\14.0\WebBrowser@HomePage)
  </VisualStudioWebBrowserHomePage>
<PropertyGroup>

警告

在 MSBuild 的 .NET SDK 版本中,dotnet build不支持注册表属性。

在执行期间创建属性

在生成评估阶段,在元素外部 Target 定位的属性分配值。 在后续执行阶段,可以创建或修改属性,如下所示:

  • 任何任务都可以发出属性。 若要发出属性,Task 元素必须具有具有属性的PropertyNameOutput 元素。

  • CreateProperty 任务可以发出属性。 此用法已弃用。

  • Target 元素可能包含 PropertyGroup 可能包含属性声明的元素。

全局属性

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

以下示例将全局 Configuration 属性设置为 DEBUG

msbuild.exe MyProj.proj -p:Configuration=DEBUG

还可以使用 Properties MSBuild 任务的属性为多项目生成中的子项目设置或修改全局属性。 全局属性也会转发到子项目, RemoveProperties 除非 MSBuild 任务的属性用于指定不转发的属性列表。 有关详细信息,请参阅 MSBuild 任务

本地属性

可以在项目中重置本地属性。 全局属性不能。 使用 -p 选项从命令行设置本地属性时,项目文件中的设置优先于命令行。

使用项目标记中的属性指定本地属性 TreatAsLocalProperty

以下代码指定两个属性是本地属性:

<Project Sdk="Microsoft.Net.Sdk" TreatAsLocalProperty="Prop1;Prop2">

本地属性不会转发到多项目生成中的子项目。 如果使用选项在命令行 -p 上提供值,则为子项目提供全局属性的值,而不是父项目中更改的本地值,但子项目(或其任何导入项)也可以自行 TreatAsLocalProperty更改。

具有本地属性的示例

下面的代码示例演示了以下效果 TreatAsLocalProperty

<!-- test1.proj -->
<Project TreatAsLocalProperty="TreatedAsLocalProp">
    <PropertyGroup>
        <TreatedAsLocalProp>LocalOverrideValue</TreatedAsLocalProp>
    </PropertyGroup>

    <Target Name="Go">
        <MSBuild Projects="$(MSBuildThisFileDirectory)\test2.proj" Targets="Go2" Properties="Inner=true" />
    </Target>

    <Target Name="Go2" BeforeTargets="Go">
        <Warning Text="TreatedAsLocalProp($(MSBuildThisFileName)): $(TreatedAsLocalProp)" />
    </Target>
</Project>
<!-- test2.proj -->
<Project TreatAsLocalProperty="TreatedAsLocalProp">
    <Target Name="Go2">
        <Warning Text="TreatedAsLocalProp($(MSBuildThisFileName)): $(TreatedAsLocalProp)" />
    </Target>
</Project>

假设你生成 test1.proj 命令行,并提供 TreatedAsLocalProperty 全局值 GlobalOverrideValue

dotnet msbuild .\test1.proj -p:TreatedAsLocalProp=GlobalOverrideValue

输出如下所示:

test1.proj(11,9): warning : TreatedAsLocalProp(test): LocalOverrideValue
test2.proj(3,9): warning : TreatedAsLocalProp(test2): GlobalOverrideValue

子项目继承全局值,但父项目使用本地集属性。

本地属性和导入

在导入的项目上使用属性时 TreatAsLocalProperty ,考虑属性获取的值时顺序非常重要。

下面的代码示例显示了对导入的项目的影响 TreatAsLocalProperty

<!-- importer.proj -->
<Project>
    <PropertyGroup>
        <TreatedAsLocalProp>FirstOverrideValue</TreatedAsLocalProp>
    </PropertyGroup>

    <Import Project="import.props" />

    <PropertyGroup>
        <TreatedAsLocalProp Condition=" '$(TrySecondOverride)' == 'true' ">SecondOverrideValue</TreatedAsLocalProp>
    </PropertyGroup>

    <Target Name="Go">
        <Warning Text="TreatedAsLocalProp($(MSBuildThisFileName)): $(TreatedAsLocalProp)" />
    </Target>
</Project>
<!-- import.proj -->
<Project TreatAsLocalProperty="TreatedAsLocalProp">
    <PropertyGroup>
        <TreatedAsLocalProp>ImportOverrideValue</TreatedAsLocalProp>
    </PropertyGroup>

    <!-- Here, TreatedAsLocalProp has the value "ImportOverrideValue"-->
</Project>

假设你生成 importer.proj 并设置一个全局值, TreatedAsLocalProp 如下所示:

dotnet msbuild .\importer.proj -p:TreatedAsLocalProp=GlobalOverrideValue

输出为:

importer.proj(9,9): warning : TreatedAsLocalProp(importer.proj): GlobalOverrideValue

现在假设使用属性 TrySecondOverride 生成为 true

dotnet msbuild .\importer.proj -p:TreatedAsLocalProp=GlobalOverrideValue -p:TrySecondOverride=true

输出为:

importer.proj(13,9): warning : TreatedAsLocalProp(importer.proj): SecondOverrideValue

该示例显示,属性在导入的项目TreatAsLocalProperty使用属性被视为本地属性,而不仅仅是导入文件中。 属性的值受全局重写值的影响,但仅在使用导入的项目TreatAsLocalProperty之前

有关详细信息,请参阅 Project 元素(MSBuild)作方法:使用不同选项生成相同的源文件

属性函数

从 .NET Framework 版本 4 开始,可以使用属性函数来评估 MSBuild 脚本。 可以读取系统时间、比较字符串、匹配正则表达式,并在生成脚本中执行许多其他作,而无需使用 MSBuild 任务。

可以使用字符串(instance)方法对任何属性值进行作,并且可以调用许多系统类的静态方法。 例如,可以将生成属性设置为今天的日期,如下所示。

<Today>$([System.DateTime]::Now.ToString("yyyy.MM.dd"))</Today>

有关详细信息,以及属性函数的列表,请参阅 属性函数

在属性中存储 XML

属性可以包含任意 XML,这有助于将值传递到任务或显示日志记录信息。 以下示例显示了该 ConfigTemplate 属性,该属性具有包含 XML 和其他属性引用的值。 MSBuild 使用各自的属性值替换属性引用。 属性值按显示的顺序进行分配。 因此,在此示例中,$(MySupportedVersion)$(MyRequiredVersion)应已定义,并且$(MySafeMode)应该已定义。

<PropertyGroup>
    <ConfigTemplate>
        <Configuration>
            <Startup>
                <SupportedRuntime
                    ImageVersion="$(MySupportedVersion)"
                    Version="$(MySupportedVersion)"/>
                <RequiredRuntime
                    ImageVersion="$(MyRequiredVersion)"
                    Version="$(MyRequiredVersion)"
                    SafeMode="$(MySafeMode)"/>
            </Startup>
        </Configuration>
    </ConfigTemplate>
</PropertyGroup>