使用 Natvis 框架在调试器中创建 C++ 对象的自定义视图Create custom views of C++ objects in the debugger using the Natvis framework

Visual Studio Natvis 框架可以自定义本机类型在调试器变量窗口(例如局部变量监视以及数据提示窗口)中显示的方式。The Visual Studio Natvis framework customizes the way native types appear in debugger variable windows, such as the Locals and Watch windows, and in DataTips. Natvis 的可视化功能可以让你创建的类型在调试期间更加直观清晰。Natvis visualizations can help make the types you create more visible during debugging.

Natvis 替换了 Visual Studio 早期版本中的 autoexp.dat 文件,提供了 XML 语法、更好的诊断功能、版本控制功能以及多文件支持功能。Natvis replaces the autoexp.dat file in earlier versions of Visual Studio with XML syntax, better diagnostics, versioning, and multiple file support.

备注

Natvis 自定义适用于类和结构,但不能适用于 typedef。Natvis customizations work with classes and structs, but not typedefs.

Natvis 可视化效果Natvis visualizations

你可以使用 Natvis 框架为自己创建的类型创建可视化规则,让开发人员在调试过程中更轻松地查看这些类型。You use the Natvis framework to create visualization rules for the types you create, so that developers can see them more easily during debugging.

例如,下图显示的类型 Windows::UI::Xaml::Controls::TextBox 的变量在调试器窗口中未应用任何自定义可视化。For example, the following illustration shows a variable of type Windows::UI::Xaml::Controls::TextBox in a debugger window without any custom visualizations applied.

TextBox 默认可视化TextBox default visualization

高亮行显示的是 TextBox 类的 Text 属性。The highlighted row shows the Text property of the TextBox class. 由于类的层次结构很复杂,因此很难找到这个属性。The complex class hierarchy makes it difficult to find this property. 调试器不知道如何解释自定义字符串类型,所以你看不到文本框中的字符串。The debugger doesn't know how to interpret the custom string type, so you can't see the string held inside the textbox.

如果应用了 Natvis 自定义可视化工具规则,那么在变量窗口中,同样的TextBox看起来就简单得多。The same TextBox looks much simpler in the variable window when Natvis custom visualizer rules are applied. 类的重要成员会显示在一起,并且调试器会显示自定义字符串类型的基础字符串值。The important members of the class appear together, and the debugger shows the underlying string value of the custom string type.

使用可视化工具的 TextBox 数据TextBox data using visualizer

在 C++ 项目中使用 .natvis 文件Use .natvis files in C++ projects

Natvis 使用 .natvis 文件指定可视化效果规则。Natvis uses .natvis files to specify visualization rules. .natvis 文件是具有 .natvis 扩展名的 XML 文件。A .natvis file is an XML file with a .natvis extension. Natvis 架构在 %VSINSTALLDIR%\Xml\Schemas\natvis.xsd 中定义。The Natvis schema is defined in %VSINSTALLDIR%\Xml\Schemas\natvis.xsd.

.natvis 文件的基本结构由一个或多个代表可视化条目的 Type 元素构成。The basic structure of a .natvis file is one or more Type elements representing visualization entries. 每个 Type 元素的完全限定名称都在其 Name 属性中指定。The fully qualified name of each Type element is specified in its Name attribute.

<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
  <Type Name="MyNamespace::CFoo">
    .
    .
  </Type>

  <Type Name="...">
    .
    .
  </Type>
</AutoVisualizer>

Visual Studio 在 %VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers 文件夹中提供了一些 .natvis 文件 。Visual Studio provides some .natvis files in the %VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers folder. 这些文件具有许多通用类型的可视化规则,可以充当有关编写新类型的可视化效果的示例。These files have visualization rules for many common types, and can serve as examples for writing visualizations for new types.

将 .natvis 文件添加到 C++ 项目Add a .natvis file to a C++ project

可以将 .natvis 文件添加到任何 C++ 项目。You can add a .natvis file to any C++ project.

若要添加新的 .natvis 文件,请执行以下操作:To add a new .natvis file:

  1. 在“解决方案资源管理器”中选择 C++ 项目节点,然后选择“项目” > “添加新项”,或右键单击项目并选择“添加” > “新项”。Select the C++ project node in Solution Explorer, and select Project > Add new item, or right-click the project and select Add > New item.

  2. 在“添加新项”对话框中,选择“Visual C++” > “实用工具” > “调试器可视化文件(.natvis)”。In the Add New Item dialog, select Visual C++ > Utility > Debugger visualization file (.natvis).

  3. 命名文件,然后选择“添加”。Name the file, and select Add.

    新文件会添加到“解决方案资源管理器”,并在 Visual Studio 文档窗格中打开。The new file is added to Solution Explorer, and opens in the Visual Studio document pane.

Visual Studio 调试器会自动在 C++ 项目中加载 .natvis 文件,默认情况下,还会在生成项目时,在 .pdb 文件中包含它们。The Visual Studio debugger loads .natvis files in C++ projects automatically, and by default, also includes them in the .pdb file when the project builds. 在调试生成的应用时,调试器会从 .pdb 文件加载 .natvis 文件,即使你没有打开该项目也是如此。If you debug the built app, the debugger loads the .natvis file from the .pdb file, even if you don't have the project open. 如果不想在 .pdb 中包含 .natvis 文件,可以从生成的 .pdb 文件中将其排除。If you don't want the .natvis file included in the .pdb, you can exclude it from the built .pdb file.

.pdb 中排除 .natvis 文件:To exclude a .natvis file from a .pdb:

  1. 解决方案资源管理器中选择 .natvis 文件,然后选择属性图标,或右键单击该文件并选择属性Select the .natvis file in Solution Explorer, and select the Properties icon, or right-click the file and select Properties.

  2. 按下从生成中排除旁边的箭头并选择,然后选择确定Drop down the arrow next to Excluded From Build and select Yes, and then select OK.

备注

如果是调试可执行的项目,则使用解决方案项来添加 .pdb 中不包含的 .natvis 文件,因为没有可用的 C++ 项目。For debugging executable projects, use the solution items to add any .natvis files that are not in the .pdb, since there is no C++ project available.

备注

.pdb 加载的 Natvis 规则仅适用于 .pdb 引用的模块中的类型。Natvis rules loaded from a .pdb apply only to the types in the modules that the .pdb refers to. 例如,如果 Module1.pdb 包含一个名为 Test 的类型的 Natvis 条目,则它仅适用于 Module1.dll 中的 Test 类。For example, if Module1.pdb has a Natvis entry for a type named Test, it only applies to the Test class in Module1.dll. 如果另一个模块也定义了一个名为 Test 的类,则 Module1.pdb 的 Natvis 条目不适用于它。If another module also defines a class named Test, the Module1.pdb Natvis entry does not apply to it.

若要通过 VSIX 包安装并注册 .natvis 文件,请执行以下操作:To install and register a .natvis file via a VSIX package:

VSIX 包可以安装和注册 .natvis 文件。A VSIX package can install and register .natvis files. 无论它们安装在何处,所有注册的 .natvis 文件都会在调试过程中自动提取。No matter where are they installed, all registered .natvis files are automatically picked up during debugging.

  1. 将 .natvis 文件包含在 VSIX 包中。Include the .natvis file in the VSIX package. 例如,对于以下项目文件:For example, for the following project file:

    <?xml version="1.0" encoding="utf-8"?>
    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
      <ItemGroup>
        <VSIXSourceItem Include="Visualizer.natvis" />
      </ItemGroup>
    </Project>
    
  2. 在 source.extension.vsixmanifest 文件中注册 .natvis 文件:Register the .natvis file in the source.extension.vsixmanifest file:

    <?xml version="1.0" encoding="utf-8"?>
    <PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
      <Assets>
        <Asset Type="NativeVisualizer" Path="Visualizer.natvis"  />
      </Assets>
    </PackageManifest>
    

Natvis 文件位置Natvis file locations

如果你希望将 .natvis 文件应用于多个项目,可以将它们添加到用户目录或系统目录中。You can add .natvis files to your user directory or to a system directory, if you want them to apply to multiple projects.

将按照以下顺序来评估 .Natvis 文件:The .natvis files are evaluated in the following order:

  1. 所调试的 .pdb 文件中内嵌的所有的 .natvis 文件,除非加载的项目中存在同名文件。Any .natvis files that are embedded in a .pdb you're debugging, unless a file of the same name exists in the loaded project.

  2. 加载的 C++ 项目或顶级解决方案中的所有 .natvis 文件。Any .natvis files that are in a loaded C++ project or top-level solution. 这包括所有已加载的 C++ 项目(包括类库),但不包括其他语言的项目。This group includes all loaded C++ projects, including class libraries, but not projects in other languages.

  3. 任何通过 VSIX 包安装和注册的 .natvis 文件。Any .natvis files installed and registered via a VSIX package.

  1. 特定于用户的 Natvis 目录 (例如, %USERPROFILE%\Documents\Visual Studio 2017\Visualizers)。The user-specific Natvis directory (for example, %USERPROFILE%\Documents\Visual Studio 2017\Visualizers).
  1. 特定于用户的 Natvis 目录 (例如, %USERPROFILE%\Documents\Visual Studio 2019\Visualizers)。The user-specific Natvis directory (for example, %USERPROFILE%\Documents\Visual Studio 2019\Visualizers).
  1. 系统级 Natvis 目录 ( %VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers)。The system-wide Natvis directory (%VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers). 此目录中包含随 Visual Studio 一起安装的 .natvis 文件。This directory has the .natvis files that are installed with Visual Studio. 如果你具有管理员权限,可以将文件添加到此目录中。If you have administrator permissions, you can add files to this directory.

在调试时修改 .natvis 文件Modify .natvis files while debugging

你可以在调试项目时,在 IDE 中修改 .natvis 文件。You can modify a .natvis file in the IDE while debugging its project. 在用于调试的同一个 Visual Studio 实例中打开该文件,进行修改,然后保存。Open the file in the same instance of Visual Studio you're debugging with, modify it, and save it. 保存后,监视局部变量窗口就会随之更新,显示所做的更改。As soon as the file is saved, the Watch and Locals windows update to reflect the change.

你还可以在调试的解决方案中添加或删除 .natvis 文件,Visual Studio 会随之添加或删除相关的可视化效果。You can also add or delete .natvis files in a solution that you're debugging, and Visual Studio adds or removes the relevant visualizations.

在调试时,无法更新 .pdb 文件中内嵌的 .natvis 文件。You can't update .natvis files that are embedded in .pdb files while you're debugging.

如果你在 Visual Studio 以外修改 .natvis 文件,所做的更改不会自动生效。If you modify the .natvis file outside of Visual Studio, the changes don't take effect automatically. 若要更新调试器窗口,可以在“即时”窗口中重新计算 .natvisreload 命令。To update the debugger windows, you can reevaluate the .natvisreload command in the Immediate window. 更改随后就会生效,无需重新启动调试会话。Then the changes take effect without restarting the debugging session.

还可以使用 .natvisreload 命令将 .natvis 文件升级到较新的版本。Also use the .natvisreload command to upgrade the .natvis file to a newer version. 例如, .natvis 文件可能被纳入了源代码管理中,并且你需要获取其他人最近所做的更改。For example, the .natvis file may be checked into source control, and you want to pick up recent changes that somebody else made.

表达式和格式化Expressions and formatting

Natvis 的可视化功能使用 C++ 表达式来指定要显示的数据项。Natvis visualizations use C++ expressions to specify the data items to display. 除了上下文运算符 (C++) 中所述的、调试器中的 C++ 表达式的增强功能和限制外,还要注意以下事项:In addition to the enhancements and limitations of C++ expressions in the debugger, which are described in Context operator (C++), be aware of the following:

  • Natvis 表达式在可视化对象上下文而非当前堆栈框架中进行计算。Natvis expressions are evaluated in the context of the object being visualized, not the current stack frame. 例如,Natvis 表达式中的 x 引用可视化对象中名为 x 的字段,而非当前函数中名为 x 的局部变量。For example, x in a Natvis expression refers to the field named x in the object being visualized, not to a local variable named x in the current function. 无法在 Natvis 表达式中访问局部变量,不过可以访问全局变量。You can't access local variables in Natvis expressions, although you can access global variables.

  • Natvis 表达式不允许函数计算或副作用。Natvis expressions don't allow function evaluation or side effects. 函数调用和赋值运算符会被忽略。Function calls and assignment operators are ignored. 由于调试器内部函数没有副作用,因此可以从任何 Natvis 表达式随意调用,即使系统不允许进行其他函数调用也是如此。Because debugger intrinsic functions are side-effect free, they may be freely called from any Natvis expression, even though other function calls are disallowed.

  • 要控制表达式的显示方式,可以使用 C++ 中的格式说明符中所述的任何格式说明符。To control how an expression displays, you can use any of the format specifiers described in Format specifiers in C++. 如果条目由 Natvis 在内部使用,格式说明符将被忽略,例如 ArrayItems 扩展中的 Size 表达式。Format specifiers are ignored when the entry is used internally by Natvis, such as the Size expression in a ArrayItems expansion.

Natvis 视图Natvis views

你可以定义不同的 Natvis 视图,以便用不同的方式来显示类型。You can define different Natvis views to display types in different ways. 例如,下面是 std::vector 的一个可视化效果,定义了一个名为 simple 的简化视图。For example, here is a visualization of std::vector that defines a simplified view named simple. 默认视图和 simple 视图中都显示了 DisplayStringArrayItems 元素,但 simple 视图中却未显示 [size][capacity] 项。The DisplayString and the ArrayItems elements show in the default view and the simple view, while the [size] and [capacity] items don't show in the simple view.

<Type Name="std::vector&lt;*&gt;">
    <DisplayString>{{ size={_Mylast - _Myfirst} }}</DisplayString>
    <Expand>
        <Item Name="[size]" ExcludeView="simple">_Mylast - _Myfirst</Item>
        <Item Name="[capacity]" ExcludeView="simple">_Myend - _Myfirst</Item>
        <ArrayItems>
            <Size>_Mylast - _Myfirst</Size>
            <ValuePointer>_Myfirst</ValuePointer>
        </ArrayItems>
    </Expand>
</Type>

监视窗口中,使用 ,view 格式说明符来指定替代视图。In the Watch window, use the ,view format specifier to specify an alternate view. simple 视图将显示为 vec,view(simple)The simple view appears as vec,view(simple):

具有简单视图的监视窗口Watch window with simple view

Natvis 错误Natvis errors

当调试器遇到可视化条目中的错误时,会忽略它们。When the debugger encounters errors in a visualization entry, it ignores them. 要么以原始格式显示类型,要么选择其他合适的可视化效果。It either displays the type in its raw form, or picks another suitable visualization. 你可以使用 Natvis 的诊断功能来了解调试器忽略可视化条目的原因,还可以查看基础语法和分析错误。You can use Natvis diagnostics to understand why the debugger ignored a visualization entry, and to see underlying syntax and parse errors.

若要启用 Natvis 诊断,请执行以下操作:To turn on Natvis diagnostics:

  • 在“工具” > “选项”(或“调试” > “选项”)>“调试” > “输出窗口”下,将“Natvis 诊断消息(仅限 C++)”设置为“错误”、“警告”或“详细” ,然后选择“确定” 。Under Tools > Options (or Debug > Options) > Debugging > Output Window, set Natvis diagnostic messages (C++ only) to Error, Warning, or Verbose, and then select OK.

错误会出现在“输出”窗口中。The errors appear in the Output window.

Natvis 语法参考Natvis syntax reference

AutoVisualizer 元素AutoVisualizer element

AutoVisualizer 元素是 .natvis 文件的根节点,并包含命名空间 xmlns: 属性。The AutoVisualizer element is the root node of the .natvis file, and contains the namespace xmlns: attribute.

<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
.
.
</AutoVisualizer>

AutoVisualizer 元素可以具有 TypeHResultUIVisualizerCustomVisualizer 子级。The AutoVisualizer element can have Type, HResult, UIVisualizer, and CustomVisualizer children.

Type 元素Type element

基本 Type 如下例所示:A basic Type looks like this example:

<Type Name="[fully qualified type name]">
  <DisplayString Condition="[Boolean expression]">[Display value]</DisplayString>
  <Expand>
    ...
  </Expand>
</Type>

Type 元素指定:The Type element specifies:

  1. 应使用可视化效果的类型(Name 特性)。What type the visualization should be used for (the Name attribute).

  2. 该类型的对象的值是什么样的( DisplayString 元素)。What the value of an object of that type should look like (the DisplayString element).

  3. 用户在变量窗口中展开类型时,该类型的成员应当以什么形式显示(Expand 节点)。What the members of the type should look like when the user expands the type in a variable window (the Expand node).

模板化类Templated classes

Type 元素的 Name 特性接受一个星号 * 作为可用于模板化类名的通配符。The Name attribute of the Type element accepts an asterisk * as a wildcard character that can be used for templated class names.

在以下示例中,无论对象是 CAtlArray<int> 还是 CAtlArray<float>,都使用了相同的可视化效果。In the following example, the same visualization is used whether the object is a CAtlArray<int> or a CAtlArray<float>. 如果 CAtlArray<float> 有特定的可视化条目,它的优先级将高于通用的条目。If there's a specific visualization entry for a CAtlArray<float>, then it takes precedence over the generic one.

<Type Name="ATL::CAtlArray&lt;*&gt;">
    <DisplayString>{{Count = {m_nSize}}}</DisplayString>
</Type>

可以使用 $T1 和 $T2 这样的宏,在可视化条目中引用模板参数。You can reference template parameters in the visualization entry by using macros $T1, $T2, and so forth. 有关这些宏的示例,请参阅 Visual Studio 随附的 .natvis 文件。To find examples of these macros, see the .natvis files shipped with Visual Studio.

可视化工具类型匹配Visualizer type matching

如果无法验证某个可视化条目,则使用下一个可用的可视化效果。If a visualization entry fails to validate, the next available visualization is used.

可继承的特性Inheritable attribute

可选的 Inheritable 属性用于指定,一个可视化效果是仅适用于一个基类型,还是适用于一个基类型和所有的派生类型。The optional Inheritable attribute specifies whether a visualization applies only to a base type, or to a base type and all derived types. Inheritable 的默认值为 trueThe default value of Inheritable is true.

在下面的示例中,可视化效果仅适用于 BaseClass 类型:In the following example, the visualization applies only to the BaseClass type:

<Type Name="Namespace::BaseClass" Inheritable="false">
    <DisplayString>{{Count = {m_nSize}}}</DisplayString>
</Type>

优先级特性Priority attribute

如果某个定义的分析失败,可选的 Priority 属性会指定使用备用定义的顺序。The optional Priority attribute specifies the order in which to use alternate definitions, if a definition fails to parse. Priority 的值包括:LowMediumLowMediumMediumHighHighThe possible values of Priority are: Low, MediumLow,Medium, MediumHigh, and High. 默认值为 MediumThe default value is Medium. Priority属性只区分同一个 .natvis 文件中的优先级。The Priority attribute distinguishes only among priorities within the same .natvis file.

下面的示例会首先分析与 2015 STL 匹配的条目。The following example first parses the entry that matches the 2015 STL. 如果分析失败,就会使用 STL 的 2013 版本的备用条目:If that fails to parse, it uses the alternate entry for the 2013 version of the STL:

<!-- VC 2013 -->
<Type Name="std::reference_wrapper&lt;*&gt;" Priority="MediumLow">
     <DisplayString>{_Callee}</DisplayString>
    <Expand>
        <ExpandedItem>_Callee</ExpandedItem>
    </Expand>
</Type>

<!-- VC 2015 -->
<Type Name="std::reference_wrapper&lt;*&gt;">
    <DisplayString>{*_Ptr}</DisplayString>
    <Expand>
        <Item Name="[ptr]">_Ptr</Item>
    </Expand>
</Type>

可选特性Optional attribute

你可以将 Optional 属性放在任一节点上。You can put an Optional attribute on any node. 如果某个可选节点内的某个子表达式的分析失败,调试器就会忽略该节点,但会应用 Type 规则的其余部分。If a subexpression inside an optional node fails to parse, the debugger ignores that node, but applies the rest of the Type rules. 在下面的类型中,[State] 不是可选的,但 [Exception] 是可选的。In the following type, [State] is non-optional, but [Exception] is optional. 如果 MyNamespace::MyClass 包含名为 M_exceptionHolder 的字段,就会同时显示 [State] 节点和 [Exception] 节点,但如果不包含 _M_exceptionHolder 字段,就会只显示 [State] 节点。If MyNamespace::MyClass has a field named _M_exceptionHolder, both the [State] node and the [Exception] node appear, but if there's no _M_exceptionHolder field, only the [State] node appears.

<Type Name="MyNamespace::MyClass">
    <Expand>
      <Item Name="[State]">_M_State</Item>
      <Item Name="[Exception]" Optional="true">_M_exceptionHolder</Item>
    </Expand>
</Type>

条件属性Condition attribute

可选的 Condition 属性可用于许多可视化元素,指定何时使用可视化规则。The optional Condition attribute is available for many visualization elements, and specifies when to use a visualization rule. 如果条件属性内的表达式解析为 false,就不应用可视化规则。If the expression inside the condition attribute resolves to false, the visualization rule doesn't apply. 如果其计算结果为 true,或者没有 Condition 属性,就会应用可视化规则。If it evaluates to true, or there is no Condition attribute, the visualization applies. 你可以将此属性用于可视化条目中的 if-else 逻辑。You can use this attribute for if-else logic in the visualization entries.

例如,下面的可视化效果具有智能指针类型的两个 DisplayString 元素。For example, the following visualization has two DisplayString elements for a smart pointer type. _Myptr 成员为空时,第一个 DisplayString 元素的条件解析为 true,以便显示窗体。When the _Myptr member is empty, the condition of the first DisplayString element resolves to true, so that form displays. _Myptr 成员不为空时,条件的计算结果为 false,且显示第二个 DisplayString 元素。When the _Myptr member is not empty, the condition evaluates to false, and the second DisplayString element displays.

<Type Name="std::auto_ptr&lt;*&gt;">
  <DisplayString Condition="_Myptr == 0">empty</DisplayString>
  <DisplayString>auto_ptr {*_Myptr}</DisplayString>
  <Expand>
    <ExpandedItem>_Myptr</ExpandedItem>
  </Expand>
</Type>

IncludeView 和 ExcludeView 特性IncludeView and ExcludeView attributes

IncludeViewExcludeView 属性用于指定是否在特定视图内显示元素。The IncludeView and ExcludeView attributes specify elements to display or not display in specific views. 例如,在下面的 Natvis std::vector 规范中,simple 视图不显示 [size][capacity] 项。For example, in the following Natvis specification of std::vector, the simple view doesn't display the [size] and [capacity] items.

<Type Name="std::vector&lt;*&gt;">
    <DisplayString>{{ size={_Mylast - _Myfirst} }}</DisplayString>
    <Expand>
        <Item Name="[size]" ExcludeView="simple">_Mylast - _Myfirst</Item>
        <Item Name="[capacity]" ExcludeView="simple">_Myend - _Myfirst</Item>
        <ArrayItems>
            <Size>_Mylast - _Myfirst</Size>
            <ValuePointer>_Myfirst</ValuePointer>
        </ArrayItems>
    </Expand>
</Type>

可以针对类型和各个成员使用 IncludeViewExcludeView 属性。You can use the IncludeView and ExcludeView attributes on types and on individual members.

Version 元素Version element

Version 元素用于将可视化条目的范围限定在特定模块和版本内。The Version element scopes a visualization entry to a specific module and version. Version 元素有助于避免名称冲突、减少无意间的不匹配,还允许在不同的类型版本中使用不同的可视化效果。The Version element helps avoid name collisions, reduces inadvertent mismatches, and allows different visualizations for different type versions.

如果某个由不同模块使用的公共头文件定义了一个类型,则只有当该类型位于指定的模块版本中时,版本化的可视化效果才会显示。If a common header file that is used by different modules defines a type, the versioned visualization appears only when the type is in the specified module version.

在下面的示例中,可视化效果只适用于在 Windows.UI.Xaml.dll 版本 1.0 到 1.5 中找到的 DirectUI::Border 类型。In the following example, the visualization is applicable only for the DirectUI::Border type found in the Windows.UI.Xaml.dll from version 1.0 to 1.5.

<Type Name="DirectUI::Border">
  <Version Name="Windows.UI.Xaml.dll" Min="1.0" Max="1.5"/>
  <DisplayString>{{Name = {*(m_pDO->m_pstrName)}}}</DisplayString>
  <Expand>
    <ExpandedItem>*(CBorder*)(m_pDO)</ExpandedItem>
  </Expand>
</Type>

不需要 MinMaxYou don't need both Min and Max. 它们是可选特性。They are optional attributes. 不支持通配符。No wildcard characters are supported.

Name 特性的格式为 filename.ext,例如 hello.exe 或 some.dll 。The Name attribute is in the format filename.ext, such as hello.exe or some.dll. 不允许使用路径名。No path names are allowed.

DisplayString 元素DisplayString element

DisplayString 元素用于指定要显示为变量值的字符串。The DisplayString element specifies a string to show as the value of a variable. 它接受混合了表达式的任意字符串。It accepts arbitrary strings mixed with expressions. 大括号内的所有内容都将被解释为表达式。Everything inside curly braces is interpreted as an expression. 例如,以下 DisplayString 条目:For instance, the following DisplayString entry:

<Type Name="CPoint">
  <DisplayString>{{x={x} y={y}}}</DisplayString>
</Type>

表示 CPoint 类型的变量显示如下图所示:Means that variables of type CPoint display as in this illustration:

使用 DisplayString 元素Use a DisplayString element

DisplayString 表达式中,属于 CPoint 成员的 xy 位于大括号内,因此它们的值会被计算。In the DisplayString expression, x and y, which are members of CPoint, are inside curly braces, so their values are evaluated. 该示例还介绍了如何用双层大括号({{}})对大括号进行转义。The example also shows how you can escape a curly brace by using double curly braces ( {{ or }} ).

备注

DisplayString 元素是唯一接受任意字符串和大括号语法的元素。The DisplayString element is the only element that accepts arbitrary strings and curly brace syntax. 所有其他可视化元素只接受调试器可以计算的表达式。All other visualization elements accept only expressions that the debugger can evaluate.

StringView 元素StringView element

StringView 元素用于定义一个值,调试器可以将该值发送给内置的文本可视化工具。The StringView element defines a value that the debugger can send to the built-in text visualizer. 例如,假设 ATL::CStringT 类型有以下可视化效果:For example, given the following visualization for the ATL::CStringT type:

<Type Name="ATL::CStringT&lt;wchar_t,*&gt;">
  <DisplayString>{m_pszData,su}</DisplayString>
</Type>

CStringT 对象将显示在一个变量窗口中,如下例所示:The CStringT object displays in a variable window like this example:

CStringT DisplayString 元素CStringT DisplayString element

添加 StringView 元素会告诉调试器,它可以将值显示为文本可视化效果。Adding a StringView element tells the debugger it can display the value as a text visualization.

<Type Name="ATL::CStringT&lt;wchar_t,*&gt;">
  <DisplayString>{m_pszData,su}</DisplayString>
  <StringView>m_pszData,su</StringView>
</Type>

在调试过程中,可以选择变量旁的放大镜图标,然后选择“文本可视化工具”以显示 m_pszData 指向的字符串。During debugging, you can select the magnifying glass icon next to the variable, and then select Text Visualizer to display the string that m_pszData points to.

使用 StringView 可视化工具的 CStringT 数据CStringT data with StringView visualizer

表达式 {m_pszData,su} 包含一个 C++ 格式说明符 su,用于将值显示为 Unicode 字符串。The expression {m_pszData,su} includes a C++ format specifier su, to display the value as a Unicode string. 有关详细信息,请参阅 C++ 中的格式说明符For more information, see Format specifiers in C++.

Expand 元素Expand element

可选的 Expand 节点用于自定义当你在变量窗口中展开类型时,该可视化类型的子项。The optional Expand node customizes the children of a visualized type when you expand the type in a variable window. Expand 节点接受用于定义子元素的子节点列表。The Expand node accepts a list of child nodes that define the child elements.

  • 如果未在可视化条目中指定 Expand 节点,子项将使用默认的展开规则。If an Expand node isn't specified in a visualization entry, the children use the default expansion rules.

  • 如果指定的 Expand 节点下面没有子节点,类型就无法在调试器窗口中展开。If an Expand node is specified with no child nodes under it, the type isn't expandable in the debugger windows.

Item 展开Item expansion

Item 元素是 Expand 节点中最基本、最常见的元素。The Item element is the most basic and common element in an Expand node. Item 用于定义单个子元素。Item defines a single child element. 例如,一个包含 topleftrightbottom 字段的 CRect 类具有以下可视化条目:For example, a CRect class with fields top, left, right, and bottom has the following visualization entry:

<Type Name="CRect">
  <DisplayString>{{top={top} bottom={bottom} left={left} right={right}}}</DisplayString>
  <Expand>
    <Item Name="Width">right - left</Item>
    <Item Name="Height">bottom - top</Item>
  </Expand>
</Type>

在调试器窗口中,CRect 类型如以下示例所示:In the debugger window, the CRect type looks like this example:

具有 Item 元素扩展的 CRectCRect with Item element expansion

调试器将计算 WidthHeight 元素中指定的表达式,然后在变量窗口的列中显示值。The debugger evaluates the expressions specified in the Width and Height elements, and shows the values in the Value column of the variable window.

调试器会为每个自定义展开自动创建 [Raw View] 节点。The debugger automatically creates the [Raw View] node for every custom expansion. 上面的屏幕截图中的 [Raw View] 节点是展开的,显示了对象的默认原始视图与其 Natvis 可视化效果的区别。The preceding screenshot displays the [Raw View] node expanded, to show how the default raw view of the object differs from its Natvis visualization. 默认展开会为基类创建一个子树,并将基类的所有数据成员以子项的形式列出。The default expansion creates a subtree for the base class, and lists all the data members of the base class as children.

备注

如果项元素的表达式指向一个复杂类型,则“项”节点本身可展开。If the expression of the item element points to a complex type, the Item node itself is expandable.

ArrayItems 展开ArrayItems expansion

使用 ArrayItems 节点,让 Visual Studio 调试器将类型解释为一个数组并显示其各个元素。Use the ArrayItems node to have the Visual Studio debugger interpret the type as an array and display its individual elements. std::vector 的可视化效果是一个很好的示例:The visualization for std::vector is a good example:

<Type Name="std::vector&lt;*&gt;">
  <DisplayString>{{size = {_Mylast - _Myfirst}}}</DisplayString>
  <Expand>
    <Item Name="[size]">_Mylast - _Myfirst</Item>
    <Item Name="[capacity]">(_Myend - _Myfirst)</Item>
    <ArrayItems>
      <Size>_Mylast - _Myfirst</Size>
      <ValuePointer>_Myfirst</ValuePointer>
    </ArrayItems>
  </Expand>
</Type>

在变量窗口中展开时,std::vector 显示了它的各个元素:A std::vector shows its individual elements when expanded in the variable window:

使用 ArrayItems 扩展的 std::vectorstd::vector using ArrayItems expansion

ArrayItems 节点必须具有:The ArrayItems node must have:

  • 用于使调试器了解数组长度的 Size 表达式(必须计算为整数)。A Size expression (which must evaluate to an integer) for the debugger to understand the length of the array.
  • 一个 ValuePointer 表达式,指向第一个元素(必须为非 void* 元素类型的指针)。A ValuePointer expression that points to the first element (which must be a pointer of an element type that is not void*).

数组下限的默认值为 0。The default value of the array lower bound is 0. 要修改此值,请使用 LowerBound 元素。To override the value, use a LowerBound element. Visual Studio 随附的 .Natvis 文件中提供了示例。The .natvis files shipped with Visual Studio have examples.

备注

可以使用 [] 运算符(例如 vector[i])以及任何使用了 ArrayItems 的一维数组可视化效果,即使该类型本身(例如 CATLArray)不允许使用此运算符。You can use the [] operator, for example vector[i], with any single-dimensional array visualization that uses ArrayItems, even if the type itself (for example CATLArray) does not allow this operator.

还可以指定多维数组。You can also specify multi-dimensional arrays. 在这种情况下,调试器需要稍多一些信息即可正确显示子元素:In that case, the debugger needs slightly more information to properly display child elements:

<Type Name="Concurrency::array&lt;*,*&gt;">
  <DisplayString>extent = {_M_extent}</DisplayString>
  <Expand>
    <Item Name="extent">_M_extent</Item>
    <ArrayItems Condition="_M_buffer_descriptor._M_data_ptr != 0">
      <Direction>Forward</Direction>
      <Rank>$T2</Rank>
      <Size>_M_extent._M_base[$i]</Size>
      <ValuePointer>($T1*) _M_buffer_descriptor._M_data_ptr</ValuePointer>
    </ArrayItems>
  </Expand>
</Type>
  • Direction 指定数组是采用行优先顺序还是列优先顺序。Direction specifies whether the array is in row-major or column-major order.
  • Rank 指定数组的秩。Rank specifies the rank of the array.
  • Size 元素接受将其替换为维索引以查找该维度中数组的长度的隐式 $i 参数。The Size element accepts the implicit $i parameter, which it substitutes with the dimension index to find the length of the array in that dimension. 在前面的示例中,表达式 _M_extent.M_base[0] 应指定第 0 个维度的长度,_M_extent._M_base[1] 应指定第 1 个维度的长度,依此类推。In the previous example, the expression _M_extent.M_base[0] should give the length of the 0th dimension, _M_extent._M_base[1] the 1st, and so on.

下面是调试器窗口中显示的一个二维 Concurrency::array 对象:Here's how a two-dimensional Concurrency::array object looks in the debugger window:

具有 ArrayItems 扩展的二维数组Two-dimensional array with ArrayItems expansion

IndexListItems 展开IndexListItems expansion

仅当数组元素在内存中连续排列时,才能使用 ArrayItems 展开。You can use ArrayItems expansion only if the array elements are laid out contiguously in memory. 调试器只需递增其指针,就可以获取下一个元素。The debugger gets to the next element by simply incrementing its pointer. 如果你需要操作值节点的索引,可以使用 IndexListItems 节点。If you need to manipulate the index to the value node, use IndexListItems nodes. 下面是 IndexListItems 节点的可视化处理:Here's a visualization with an IndexListItems node:

<Type Name="Concurrency::multi_link_registry&lt;*&gt;">
  <DisplayString>{{size = {_M_vector._M_index}}}</DisplayString>
  <Expand>
    <Item Name="[size]">_M_vector._M_index</Item>
    <IndexListItems>
      <Size>_M_vector._M_index</Size>
      <ValueNode>*(_M_vector._M_array[$i])</ValueNode>
    </IndexListItems>
  </Expand>
</Type>

ArrayItemsIndexListItems 之间的唯一区别是 ValueNode,它期望带有隐式元素 $i 参数的第 i 个元素的完整表达式。The only difference between ArrayItems and IndexListItems is the ValueNode, which expects the full expression to the ith element with the implicit $i parameter.

备注

可以使用 [] 运算符(例如 vector[i])以及任何使用了 IndexListItems 的一维数组可视化效果,即使该类型本身(例如 CATLArray)不允许使用此运算符。You can use the [] operator, for example vector[i], with any single-dimensional array visualization that uses IndexListItems, even if the type itself (for example CATLArray) does not allow this operator.

LinkedListItems 展开LinkedListItems expansion

如果可视化类型表示一个链接列表,则调试器可以通过使用 LinkedListItems 节点显示其子级。If the visualized type represents a linked list, the debugger can display its children by using a LinkedListItems node. CAtlList 类型的以下可视化效果使用 LinkedListItemsThe following visualization for the CAtlList type uses LinkedListItems:

<Type Name="ATL::CAtlList&lt;*,*&gt;">
  <DisplayString>{{Count = {m_nElements}}}</DisplayString>
  <Expand>
    <Item Name="Count">m_nElements</Item>
    <LinkedListItems>
      <Size>m_nElements</Size>
      <HeadPointer>m_pHead</HeadPointer>
      <NextPointer>m_pNext</NextPointer>
      <ValueNode>m_element</ValueNode>
    </LinkedListItems>
  </Expand>
</Type>

Size 元素引用该列表的长度。The Size element refers to the length of the list. HeadPointer 指向第一个元素, NextPointer 引用下一个元素,而 ValueNode 引用项的值。HeadPointer points to the first element, NextPointer refers to the next element, and ValueNode refers to the value of the item.

调试器将在 LinkedListItems 节点元素(而不是父列表类型)环境中计算 NextPointerValueNode 表达式。The debugger evaluates the NextPointer and ValueNode expressions in the context of the LinkedListItems node element, not the parent list type. 在前面的示例中,CAtlList 有一个 CNode 类(位于 atlcoll.h 中),它是链接列表的节点。In the preceding example, CAtlList has a CNode class (found in atlcoll.h) that is a node of the linked list. m_pNextm_elementCNode 类(而不是 CAtlList 类)的字段。m_pNext and m_element are fields of that CNode class, not of the CAtlList class.

ValueNode 可以保留为空或使用 this 来引用 LinkedListItems 节点本身。ValueNode can be left empty, or use this to refer to the LinkedListItems node itself.

CustomListItems 展开CustomListItems expansion

借助 CustomListItems 展开,你可以编写自定义逻辑,用于遍历哈希表等数据结构。The CustomListItems expansion allows you to write custom logic for traversing a data structure such as a hashtable. 使用 CustomListItems 来可视化数据结构,这些数据结构可以使用 C++ 表达式进行所有运算,但不太适合 ArrayItemsIndexListItemsLinkedListItems 模式。Use CustomListItems to visualize data structures that can use C++ expressions for everything you need to evaluate, but don't quite fit the mold for ArrayItems, IndexListItems, or LinkedListItems.

借助在展开内定义的变量和对象,你可以在 CustomListItems 展开中使用 Exec 来执行内部代码。You can use Exec to execute code inside of a CustomListItems expansion, using the variables and objects defined in the expansion. 可以将逻辑运算符、算术运算符和赋值运算符与 Exec 一起使用。You can use logical operators, arithmetic operators, and assignment operators with Exec. 无法使用 Exec 计算函数,除了 C++ 表达式计算器支持的调试器内部函数You can't use Exec to evaluate functions, except for debugger intrinsic functions supported by the C++ expression evaluator.

下面的 CAtlMap 可视化工具是一个很好的例子,其中的 CustomListItems 用得很恰当。The following visualizer for CAtlMap is an excellent example where CustomListItems is appropriate.

<Type Name="ATL::CAtlMap&lt;*,*,*,*&gt;">
    <AlternativeType Name="ATL::CMapToInterface&lt;*,*,*&gt;"/>
    <AlternativeType Name="ATL::CMapToAutoPtr&lt;*,*,*&gt;"/>
    <DisplayString>{{Count = {m_nElements}}}</DisplayString>
    <Expand>
      <CustomListItems MaxItemsPerView="5000" ExcludeView="Test">
        <Variable Name="iBucket" InitialValue="-1" />
        <Variable Name="pBucket" InitialValue="m_ppBins == nullptr ? nullptr : *m_ppBins" />
        <Variable Name="iBucketIncrement" InitialValue="-1" />

        <Size>m_nElements</Size>
        <Exec>pBucket = nullptr</Exec>
        <Loop>
          <If Condition="pBucket == nullptr">
            <Exec>iBucket++</Exec>
            <Exec>iBucketIncrement = __findnonnull(m_ppBins + iBucket, m_nBins - iBucket)</Exec>
            <Break Condition="iBucketIncrement == -1" />
            <Exec>iBucket += iBucketIncrement</Exec>
            <Exec>pBucket = m_ppBins[iBucket]</Exec>
          </If>
          <Item>pBucket,na</Item>
          <Exec>pBucket = pBucket->m_pNext</Exec>
        </Loop>
      </CustomListItems>
    </Expand>
</Type>

TreeItems 展开TreeItems expansion

如果可视化类型表示一个树,则调试器可以通过使用 TreeItems 节点遍历该树并显示其子级。If the visualized type represents a tree, the debugger can walk the tree and display its children by using a TreeItems node. 下面是使用 TreeItems 节点的 std::map 类型的可视化效果:Here's the visualization for the std::map type using a TreeItems node:

<Type Name="std::map&lt;*&gt;">
  <DisplayString>{{size = {_Mysize}}}</DisplayString>
  <Expand>
    <Item Name="[size]">_Mysize</Item>
    <Item Name="[comp]">comp</Item>
    <TreeItems>
      <Size>_Mysize</Size>
      <HeadPointer>_Myhead->_Parent</HeadPointer>
      <LeftPointer>_Left</LeftPointer>
      <RightPointer>_Right</RightPointer>
      <ValueNode Condition="!((bool)_Isnil)">_Myval</ValueNode>
    </TreeItems>
  </Expand>
</Type>

语法类似于 LinkedListItems 节点。The syntax is similar to the LinkedListItems node. LeftPointerRightPointerValueNode 是在树节点类的上下文中计算的。LeftPointer, RightPointer, and ValueNode are evaluated under the context of the tree node class. ValueNode 可以保留为空或使用 this 来引用 TreeItems 节点本身。ValueNode can be left empty or use this to refer to the TreeItems node itself.

ExpandedItem 展开ExpandedItem expansion

通过将基类或数据成员的属性显示为可视化类型的子项,ExpandedItem 元素生成了一个聚合的子视图。The ExpandedItem element generates an aggregated child view by displaying properties of base classes or data members as if they were children of the visualized type. 调试器将计算指定的表达式,并将结果的子节点附加到该可视化类型的子列表中。The debugger evaluates the specified expression, and appends the child nodes of the result to the child list of the visualized type.

例如,智能指针类型 auto_ptr<vector<int>> 通常显示为:For example, the smart pointer type auto_ptr<vector<int>> typically displays as:

auto_ptr<vector<int>> 默认扩展auto_ptr<vector<int>> default expansion

要查看矢量的值,就必须在变量窗口中穿过 _Myptr 成员,向下深入两个级别。To see the values of the vector, you have to drill down two levels in the variable window, passing through the _Myptr member. 通过添加 ExpandedItem 元素,就可以从层次结构中去除 _Myptr 变量并直接查看矢量元素:By adding an ExpandedItem element, you can eliminate the _Myptr variable from the hierarchy and directly view the vector elements:

<Type Name="std::auto_ptr&lt;*&gt;">
  <DisplayString>auto_ptr {*_Myptr}</DisplayString>
  <Expand>
    <ExpandedItem>_Myptr</ExpandedItem>
  </Expand>
</Type>

auto_ptr<vector<int>> ExpandedItem 扩展auto_ptr<vector<int>> ExpandedItem expansion

下面的示例介绍了如何将基类的属性聚合到一个派生类中。The following example shows how to aggregate properties from the base class in a derived class. 假设 CPanel 类派生自 CFrameworkElementSuppose the CPanel class derives from CFrameworkElement. ExpandedItem 节点的可视化会将基 CFrameworkElement 类的属性附加到 CPanel 类的子列表中,而不是重复这些属性。Instead of repeating the properties that come from the base CFrameworkElement class, the ExpandedItem node visualization appends those properties to the child list of the CPanel class.

<Type Name="CPanel">
  <DisplayString>{{Name = {*(m_pstrName)}}}</DisplayString>
  <Expand>
    <Item Name="IsItemsHost">(bool)m_bItemsHost</Item>
    <ExpandedItem>*(CFrameworkElement*)this,nd</ExpandedItem>
  </Expand>
</Type>

关闭派生类的可视化匹配的 nd 格式说明符肯定在这。The nd format specifier, which turns off visualization matching for the derived class, is necessary here. 否则,表达式 *(CFrameworkElement*)this 会导致再次应用 CPanel 可视化效果,因为默认可视化类型匹配规则认为它是最适合的选项。Otherwise, the expression *(CFrameworkElement*)this would cause the CPanel visualization to be applied again, because the default visualization type matching rules consider it the most appropriate one. 使用 nd 格式说明符指示调试器使用基类可视化效果或默认扩展(如果基类没有可视化效果)。Use the nd format specifier to instruct the debugger to use the base class visualization, or the default expansion if the base class has no visualization.

Synthetic Item 展开Synthetic item expansion

ExpandedItem 元素通过消除层次结构提供更简单的数据视图,Synthetic 节点则恰好相反。While the ExpandedItem element provides a flatter view of data by eliminating hierarchies, the Synthetic node does the opposite. 它允许你创建人工子元素(不是表达式的结果)。It allows you to create an artificial child element that isn't a result of an expression. 人工元素可以具有其自己的子元素。The artificial element can have child elements of its own. 在下面的示例中, Concurrency::array 类型的可视化效果使用 Synthetic 节点向用户显示诊断消息:In the following example, the visualization for the Concurrency::array type uses a Synthetic node to show a diagnostic message to the user:

<Type Name="Concurrency::array&lt;*,*&gt;">
  <DisplayString>extent = {_M_extent}</DisplayString>
  <Expand>
    <Item Name="extent" Condition="_M_buffer_descriptor._M_data_ptr == 0">_M_extent</Item>
    <ArrayItems Condition="_M_buffer_descriptor._M_data_ptr != 0">
      <Rank>$T2</Rank>
      <Size>_M_extent._M_base[$i]</Size>
      <ValuePointer>($T1*) _M_buffer_descriptor._M_data_ptr</ValuePointer>
    </ArrayItems>
    <Synthetic Name="Array" Condition="_M_buffer_descriptor._M_data_ptr == 0">
      <DisplayString>Array members can be viewed only under the GPU debugger</DisplayString>
    </Synthetic>
  </Expand>
</Type>

具有 Synthetic 元素扩展的 Concurrency::ArrayConcurrency::Array with Synthetic element expansion

HResult 元素HResult element

借助 HResult 元素,你可以自定义显示在调试器窗口中的 HRESULT 信息。The HResult element lets you customize the information shown for an HRESULT in debugger windows. HRValue 元素必须包含要自定义的 HRESULT 的 32 位值。The HRValue element must contain the 32-bit value of the HRESULT that is to be customized. HRDescription 元素包含要显示在调试器窗口中的信息。The HRDescription element contains the information to show in the debugger window.


<HResult Name="MY_E_COLLECTION_NOELEMENTS">
  <HRValue>0xABC0123</HRValue>
  <HRDescription>No elements in the collection.</HRDescription>
</HResult>

UIVisualizer 元素UIVisualizer element

UIVisualizer 元素用于向调试器注册图形可视化工具插件。A UIVisualizer element registers a graphical visualizer plug-in with the debugger. 图形可视化工具会创建一个对话框或其他界面,用符合其数据类型的方式显示变量或对象。A graphical visualizer creates a dialog box or other interface that shows a variable or object in a way consistent with its data type. 可视化工具插件必须被编写为 VSPackage,并且必须公开一项调试器可以使用的服务。The visualizer plug-in must be authored as a VSPackage, and must expose a service that the debugger can consume. .Natvis 文件包含插件的注册信息,例如名称、所公开服务的 GUID 以及它可以直观显示的类型。The .natvis file contains registration information for the plug-in, such as its name, the GUID of the exposed service, and the types it can visualize.

下面是 UIVisualizer 元素的示例:Here's an example of a UIVisualizer element:

<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
    <UIVisualizer ServiceId="{5452AFEA-3DF6-46BB-9177-C0B08F318025}"
        Id="1" MenuName="Vector Visualizer"/>
    <UIVisualizer ServiceId="{5452AFEA-3DF6-46BB-9177-C0B08F318025}"
        Id="2" MenuName="List Visualizer"/>
.
.
</AutoVisualizer>
  • ServiceId - Id 属性对用来标识 UIVisualizerA ServiceId - Id attribute pair identifies a UIVisualizer. ServiceId 是可视化工具包公开的服务的 GUID。The ServiceId is the GUID of the service the visualizer package exposes. 如果服务提供了多个可视化工具,Id 是用来区分它们的唯一标识符。Id is a unique identifier that differentiates visualizers, if a service provides more than one. 在上面的示例中,同一个可视化工具服务提供了两个可视化工具。In the preceding example, the same visualizer service provides two visualizers.

  • MenuName 属性用于定义可视化工具名称,该名称会显示在调试器的放大镜图标旁边的下拉列表中。The MenuName attribute defines a visualizer name to display in the drop-down next to the magnifying glass icon in the debugger. 例如:For example:

    UIVisualizer 菜单快捷菜单UIVisualizer menu shortcut menu

.natvis 文件中定义的每种类型都必须明确列出能够显示它的所有 UI 可视化工具。Each type defined in the .natvis file must explicitly list any UI visualizers that can display it. 调试器会将类型条目中的可视化工具引用与注册的可视化工具相匹配。The debugger matches the visualizer references in the type entries with the registered visualizers. 例如,下面的 std::vector 类型条目引用的是前一个示例中的 UIVisualizerFor example, the following type entry for std::vector references the UIVisualizer in the preceding example.

<Type Name="std::vector&lt;int,*&gt;">
  <UIVisualizer ServiceId="{5452AFEA-3DF6-46BB-9177-C0B08F318025}" Id="1" />
</Type>

可在用于查看内存中位图的图像监视扩展中看到 UIVisualizer 的示例。You can see an example of a UIVisualizer in the Image Watch extension used to view in-memory bitmaps.

CustomVisualizer 元素CustomVisualizer element

CustomVisualizer 是一个扩展点,用于指定你编写的 VSIX 扩展,以便在 Visual Studio 代码中控制可视化效果。CustomVisualizer is an extensibility point that specifies a VSIX extension that you write to control visualizations in Visual Studio code. 有关编写 VSIX 扩展的更多信息,请参阅 Visual Studio SDKFor more information about writing VSIX extensions, see the Visual Studio SDK.

编写自定义可视化工具比 XML Natvis 定义要费事得多,但 Natvis 在支持方面的限制对你没有影响。It's a lot more work to write a custom visualizer than an XML Natvis definition, but you're free from constraints about what Natvis does or doesn't support. 自定义可视化工具有权访问所有的调试器扩展性 API,因此可以查询和修改调试对象进程,也可以与 Visual Studio 的其他部分通信。Custom visualizers have access to the full set of debugger extensibility APIs, which can query and modify the debuggee process or communicate with other parts of Visual Studio.

可以在 CustomVisualizer 元素上使用 ConditionIncludeViewExcludeView 属性。You can use the Condition, IncludeView, and ExcludeView attributes on CustomVisualizer elements.

限制Limitations

Natvis 自定义适用于类和结构,但不能适用于 typedef。Natvis customizations work with classes and structs, but not typedefs.

对于基元类型(例如 intbool)或指向基元类型的指针,Natvis 不支持可视化工具。Natvis does not support visualizers for primitive types (for example, int, bool) or for pointers to primitive types. 在此方案中,一种选择是使用适合于用例的格式说明符In this scenario, one option is to use the format specifier appropriate to your use case. 例如,如果在代码中使用 double* mydoublearray,则可以在调试器的“监视”窗口中使用数组格式说明符,如显示前 100 个元素的表达式 mydoublearray, [100]For example, if you use double* mydoublearray in your code, then you can use an array format specifier in the debugger's Watch window, such as the expression mydoublearray, [100], which shows the first 100 elements.