MSBuild 属性
属性是可用于配置生成的名称/值对。 属性可用于将值传递给任务,评估条件和存储将在整个项目文件中引用的值。
在项目文件中定义和引用属性
属性的声明方式是:创建一个与属性同名的元素,将其指定为 PropertyGroup 元素的子元素。 例如,下面的 XML 将创建一个名为 BuildDir
的属性,其值为 Build
。
<PropertyGroup>
<BuildDir>Build</BuildDir>
</PropertyGroup>
有效属性的名称以大写或小写字母或下划线 (_
) 开头;有效的后续字符包括字母数字字符(字母或数字)、下划线和连字符 (-
)。
在整个项目文件中,可使用语法 $(<PropertyName>)
来引用各个属性。 例如,上一示例中的属性是使用 $(BuildDir)
引用的。
属性值可通过重新定义属性进行更改。 使用以下 XML可赋予 BuildDir
属性新值:
<PropertyGroup>
<BuildDir>Alternate</BuildDir>
</PropertyGroup>
属性按其在项目中的显示顺序进行评估。 分配旧值后,必须声明 BuildDir
的新值。
预留属性
MSBuild 保留了一些属性名称,用于存储有关项目文件和 MSBuild 二进制文件的信息。 与其他属性一样,可使用 $ 符号引用这些属性。 例如,$(MSBuildProjectFile) 会返回项目文件的完整文件名,包括文件扩展名。
有关详细信息,请参阅如何:引用项目文件的名称或位置和 MSBuild 保留和常见属性。
MSBuild 内部属性
在以下划线 (_) 开头的标准导入文件中定义的属性对 MSBuild 是专用属性,不应在用户代码中读取、重置或替代。
环境属性
可以引用项目文件中的环境变量,方法与引用保留属性相同。 例如,若要使用项目文件中的 PATH
环境变量,可使用 $(Path)。 如果项目包含与环境属性具有相同名称的属性定义,则项目中的属性将覆盖环境变量的值。
每个 MSBuild 项目都有一个独立环境块:它只能识别对自己块的读写操作。 在计算或生成项目文件之前,MSBuild 只在初始化属性集合时读取环境变量。 在此之后,环境属性是静态的,也就是说,每个生成工具使用相同的名称和值启动。
若要从生成工具中获取环境变量的当前值,请使用属性函数 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>
警告
在 .NET SDK 版本的 MSBuild (dotnet build
) 中,不支持注册表属性。
在执行过程中创建属性
在生成的评估阶段会为 Target
元素外的属性分配值。 在后续执行阶段中,可按以下方式创建或修改属性:
任何任务都可以发出属性。 若要发出属性,Task 元素必须具有含有
PropertyName
属性的 Output 子元素。CreateProperty 任务可发出属性。 此用法已弃用。
Target
元素可能会包含PropertyGroup
元素,后者可能会包含属性声明。
全局属性
借助 MSBuild,可使用 -property (或 -p )开关在命令行中设置属性。 这些全局属性值会覆盖项目文件中设置的属性值。 这包括环境属性,但不包括不能更改的保留属性。
以下示例将全局 Configuration
属性设置为 DEBUG
。
msbuild.exe MyProj.proj -p:Configuration=DEBUG
还可使用 MSBuild 任务的 Properties
属性为多项目生成中的子项目设置或修改全局属性。 除非使用 MSBuild 任务的 RemoveProperties
属性来指定不准备转发的属性列表,否则全局属性同样会转发到子项目。 有关详细信息,请参阅 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 任务。
可使用字符串(实例)方法来操作任何属性值,并且还可调用许多系统类的静态方法。 例如,可按如下所示将生成属性设置为当天的日期。
<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>