属性是可用于配置生成的名称/值对。 属性可用于将值传递到任务、评估条件和存储将在整个项目文件中引用的值。
在项目文件中定义和引用属性
属性的声明方式是:创建一个与属性同名的元素作为 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 元素必须具有具有属性的
PropertyName
子 Output 元素。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>