IDE 中的项目属性页是由默认规则文件夹中的 XML 文件配置的。 XML 文件描述规则名称、类别以及各个属性、其数据类型、默认值和显示方式。 在 IDE 中设置属性时,新值存储在项目文件中。
默认规则文件夹的路径取决于区域设置和所用的 Visual Studio 版本。 在 Visual Studio 2015 或更早版本的开发人员命令提示符中,规则文件夹为 %ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\<version>\<locale>。 在 Visual Studio 2015 中,<version> 值为 v140。 <locale> 为 LCID,例如,用于英语的 1033。 对于安装的每个 Visual Studio 版本和每种语言,将使用不同的路径。 例如,Visual Studio 2015 Community 英文版的默认规则文件夹路径可能是 C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\v140\1033\。
默认规则文件夹的路径取决于区域设置和所用的 Visual Studio 版本。 在 Visual Studio 2017 的开发人员命令提示符中,规则文件夹为 %VSINSTALLDIR%Common7\IDE\VC\VCTargets\<locale>\。 <locale> 为 LCID,例如,用于英语的 1033。 在 Visual Studio 2015 或更早版本的开发人员命令提示符中,规则文件夹为 %ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\<version>\<locale>\,其中 <version> 值是 Visual Studio 2015 中的 v140。 对于安装的每个 Visual Studio 版本和每种语言,将使用不同的路径。 例如,Visual Studio 2017 Community 英文版的默认规则文件夹路径可能是 C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\VC\VCTargets\1033\。
默认规则文件夹的路径取决于区域设置和所用的 Visual Studio 版本。 在 Visual Studio 2019 或更高版本的开发人员命令提示符中,规则文件夹为 %VSINSTALLDIR%MSBuild\Microsoft\VC\<version>\<locale>\,其中 <version> 值是 Visual Studio 2019 中的 v160。 <locale> 为 LCID,例如,用于英语的 1033。 在 Visual Studio 2017 中,规则文件夹为 %VSINSTALLDIR%Common7\IDE\VC\VCTargets\<locale>\。 在 Visual Studio 2015 或更早版本的开发人员命令提示符中,规则文件夹为 %ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\<version>\<locale>\。 对于安装的每个 Visual Studio 版本和每种语言,将使用不同的路径。 例如,Visual Studio 2019 Community 英文版的默认规则文件夹路径可能是 C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\1033\。
你只需了解这些文件和 Visual Studio IDE 在几个场景中的内部工作原理:
- 你要创建自定义属性页,或
- 你希望在不使用 Visual Studio IDE 的情况下自定义项目属性。
规则文件的内容
首先,让我们打开一个项目的属性页。 右键单击“解决方案资源管理器”中的项目节点,并选择“属性”:

“配置属性”下的每个节点都称为一个规则。 规则有时代表一个工具,例如编译器。 一般情况下,该术语指的是具有属性、可执行的并可能生成一些输出的工具。 每个规则都是从默认规则文件夹中的 XML 文件填充的。 例如,此处显示的 C/C++ 规则由 cl.xml 填充。
每个规则都具有一组属性,这些属性按类别整理。 规则下的每个子节点代表一个类别。 例如,“C/C++”下的“优化”节点包含编译器工具的所有优化相关属性。 这些属性及其值在右窗格上以网格形式呈现。
可以在记事本或任何 XML 编辑器中打开 cl.xml。 你将看到一个名为 Rule 的根节点。 该节点定义了在 UI 中显示的相同属性列表以及其他元数据。
<?xml version="1.0" encoding="utf-8"?>
<!--Copyright, Microsoft Corporation, All rights reserved.-->
<Rule Name="CL" PageTemplate="tool" DisplayName="C/C++" SwitchPrefix="/" Order="10" xmlns="http://schemas.microsoft.com/build/2009/properties" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Rule.Categories>
<Category Name="General" DisplayName="General" />
<Category Name="Optimization" DisplayName="Optimization" />
<Category Name="Preprocessor" DisplayName="Preprocessor" />
<Category Name="Code Generation" DisplayName="Code Generation" />
<Category Name="Language" DisplayName="Language" />
<Category Name="Precompiled Headers" DisplayName="Precompiled Headers" />
<Category Name="Output Files" DisplayName="Output Files" />
<Category Name="Browse Information" DisplayName="Browse Information" />
<Category Name="Advanced" DisplayName="Advanced" />
<Category Name="All Options" DisplayName="All Options" Subtype="Search" />
<Category Name="Command Line" DisplayName="Command Line" Subtype="CommandLine" />
</Rule.Categories>
<!-- . . . -->
</Rule>
属性页 UI 中的“配置属性”下的每个节点都有一个 XML 文件。 可以在 UI 中添加或删除规则,方法是在项目中包含或删除相应 XML 文件的位置。 例如,Microsoft.CppBuild.targets(比 1033 文件夹高一个级别)包含 cl.xml:
<PropertyPageSchema Condition="'$(ConfigurationType)' != 'Utility'" Include="$(VCTargetsPath)$(LangID)\cl.xml"/>
如果去除所有数据的 cl.xml,则会得到以下基本框架:
<?xml version="1.0" encoding="utf-8"?>
<Rule>
<Rule.DataSource />
<Rule.Categories>
<Category />
<!-- . . . -->
</Rule.Categories>
<BoolProperty />
<EnumProperty />
<IntProperty />
<StringProperty />
<StringListProperty />
</Rule>
下一部分将介绍每个主要元素和可以附加的一些元数据。
规则特性
<Rule> 元素是 XML 文件中的根节点。 它可以包含很多特性:
<Rule Name="CL" PageTemplate="tool" SwitchPrefix="/" Order="10"
xmlns="http://schemas.microsoft.com/build/2009/properties"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Rule.DisplayName>
<sys:String>C/C++</sys:String>
</Rule.DisplayName>
Name:Name 特性是Rule的 ID。 在项目的所有属性页 XML 文件中,它必须是唯一的。PageTemplate:UI 使用此特性的值从 UI 模板集合中进行选择。 “工具”模板以标准网格形式呈现属性。 此特性的其他内置值为“调试程序”和“通用”。 请分别查看“调试”节点和“常规”节点,以查看指定这些值所产生的 UI 格式。 “调试器”页面模板的 UI 使用下拉框在不同调试器的属性之间切换。 “泛型”模板在一个页面中显示不同的属性类别,而不是在Rule节点下包含多个类别子节点。 此特性只是对 UI 的建议。 XML 文件独立于 UI。 不同的 UI 可能出于不同目的使用此特性。SwitchPrefix:命令行中用于开关的前缀。 如果指定值"/",则会创建类似于/ZI、/nologo、/W3等的开关。Order:建议针对此Rule相对于系统中所有其他规则的相对位置的潜在 UI 客户端。xmlns:标准的 XML 元素。 可以看到三个列出的命名空间。 这些特性分别对应于 XML 反序列化类命名空间、XML 架构命名空间和系统命名空间。DisplayName:在Rule节点的属性页 UI 上显示的名称。 此值已本地化。 由于内部本地化工具要求,我们将创建DisplayName作为Rule的子元素而不是特性(例如Name或SwitchPrefix)。 从 XML 的角度看,两者是等效的。 因此,可以仅将其用作用于减少混乱或保持原样的特性。DataSource:此重要属性向项目系统告知读取和写入属性值的位置及其分组(稍后将说明)。 对于cl.xml,这些值为:<DataSource Persistence="ProjectFile" ItemType="ClCompile" Label="" HasConfigurationCondition="true" />Persistence="ProjectFile"告知项目系统应写入项目文件或属性表文件(取决于用于生成属性页的节点)的Rule的所有属性。 其他可能的值为"UserFile",即,将值写入.user文件。ItemType="ClCompile"表示属性将存储为 ItemDefinition 元数据或此项类型的项元数据(后者仅在属性页从解决方案资源管理器中的文件节点生成的情况下适用)。 如果未设置此字段,则属性写入为 PropertyGroup 中的常见属性。Label=""指示在属性写入为ItemDefinition元数据时,父级 ItemDefinitionGroup 的标签将为空(每个 MSBuild 元素都可以有一个标签)。 Visual Studio 2017 和更高版本使用已标记的组来导航 vcxproj 项目文件。 包含大多数Rule属性的组都具有空字符串作为标签。HasConfigurationCondition="true"指示项目系统为值附加配置条件,以便其仅对当前项目配置生效(该条件可以附加到父组或值本身)。 例如,打开项目节点的属性页,并将“配置属性”>“C/C++ 常规”下的“将警报视为错误”属性值设为“是”。 以下值将写入项目文件中。 请注意附加到父级 ItemDefinitionGroup 的配置条件。<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> </ItemDefinitionGroup>如果在特定文件(例如
stdafx.cpp)的属性页中设置此值,则该属性值将在项目文件中的stdafx.cpp项下写入,如下所示。 请注意将配置条件直接附加到元数据本身的方式:<ItemGroup> <ClCompile Include="stdafx.cpp"> <TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</TreatWarningAsError> </ClCompile> </ItemGroup>
此处未列出的另一个
DataSource特性是PersistedName。 通过此特性,可以使用不同的名称表示项目文件中的属性。 默认情况下,此特性设置为属性的Name。单个属性可以重写其父
Rule的DataSource。 在这种情况下,此属性值的位置将不同于Rule中其他属性的位置。此处未显示
Rule的其他某些特性(包括Description和SupportsFileBatching)。 通过浏览这些类型的文档,可以获得适用于Rule或任何其他元素的完整特性集。 或者,可以检查Microsoft.Build.Framework.dll程序集中Microsoft.Build.Framework.XamlTypes命名空间中的类型的公共属性。DisplayName、PageTemplate和Order是独立于 UI 的数据模型中存在的 UI 相关属性。 用于显示属性页的任何 UI 几乎肯定会使用这些属性。DisplayName和Description这两个属性几乎存在于 XML 文件中的所有元素上。 此外,只有这两个属性已本地化。
类别元素
一个 Rule 可以有多个 Category 元素。 XML 文件中列出类别的顺序是让 UI 以相同顺序显示类别的建议。 例如,在 UI 中看到的“C/C++”节点下的类别顺序与 cl.xml 中的顺序相同。 示例类别如下所示:
<Category Name="Optimization">
<Category.DisplayName>
<sys:String>Optimization</sys:String>
</Category.DisplayName>
</Category>
此代码片段演示了前面所述的 Name 和 DisplayName 特性。 同样,示例中未显示 Category 可以包含的其他一些特性。 可以通过阅读文档或使用 ildasm.exe 检查程序集来了解相关信息。
属性元素
大多数规则文件由 Property 元素组成。 这些元素包含 Rule 中所有属性的列表。 每个属性可以是基本框架中显示的五种可能类型之一:BoolProperty、EnumProperty、IntProperty、StringProperty 和 StringListProperty。 你的文件中可能只有上述几种类型。 一个属性包含多个特性,可对属性进行详细描述。 此处描述了 StringProperty。 其余的属性是类似的。
<StringProperty Subtype="file" Name="ObjectFileName" Category="Output Files" Switch="Fo">
<StringProperty.DisplayName>
<sys:String>Object File Name</sys:String>
</StringProperty.DisplayName>
<StringProperty.Description>
<sys:String>Specifies a name to override the default object file name; can be file or directory name.(/Fo[name])</sys:String>
</StringProperty.Description>
</StringProperty>
此代码片段中的大部分特性上文前都已介绍过。 新特性包括 Subtype、Category 和 Switch。
Subtype是仅适用于StringProperty和StringListProperty元素的特性。 它提供上下文信息。 例如,file值指示该属性表示文件路径。 Visual Studio 使用这种上下文信息来增强编辑体验。 例如,它可以提供一个 Windows 资源管理器窗口作为属性的编辑器,使用户能够直观地选择文件。Category:此属性所属的类别。 尝试在 UI 的“输出文件”类别下查找此属性。Switch:当规则表示编译器工具之类的工具时,大多数Rule属性会在生成时作为开关传递给工具可执行文件。 此特性的值指示要使用的开关文本。<StringProperty>示例指定其开关应为Fo。 此属性结合父Rule上的SwitchPrefix特性作为/Fo"Debug\"传递给可执行文件。 它在属性页 UI 中的 C/C++ 命令行中可见。其他属性特性包括:
Visible:如果你不希望属性出现在属性页中,但希望它在生成时可用,请将此特性设置为false。ReadOnly:如果你希望在属性页中提供此属性值的只读视图,请将此特性设置为true。IncludeInCommandLine:在生成时,工具可能不需要其某些属性。 将此特性设置为false以防止传递特定的属性。