AutoVisualizer 元素

AutoVisualizer 元素是 .natvis 文件的根节点,并包含命名空间 xmlns: 属性。

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

AutoVisualizer 元素可以具有类型、 HResult、 UIVisualizer和CustomVisualizer子项。

Type 元素

基本 Type 如下例所示:

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

Type 元素指定:

  1. 可视化对象应使用的类型(Name 特性)。

  2. 该类型的对象的值是什么样的( DisplayString 元素)。

  3. 用户在变量窗口中展开类型时,该类型的成员应当以什么形式显示(Expand 节点)。

模板类

Type 元素的 Name 属性接受星号 * 作为可用于模板化类名的通配符。

如果 CAtlArray<float> 有特定的可视化条目,它的优先级将高于通用的条目。

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

有关这些宏的示例,请参阅 Visual Studio 随附的 .natvis 文件。

可视化工具类型匹配

如果无法验证某个可视化条目,则使用下一个可用的可视化效果。

可继承的特性

Inheritable 的默认值为 true

在下面的示例中,可视化效果仅适用于 BaseClass 类型:

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

优先级特性

Priority属性只区分同一个 .natvis 文件中的优先级。

如果分析失败,就会使用 STL 的 2013 版本的备用条目:

XML
<!-- 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>

可选特性

如果 MyNamespace::MyClass 包含名为 M_exceptionHolder 的字段,就会同时显示 [State] 节点和 [Exception] 节点,但如果不包含 _M_exceptionHolder 字段,就会只显示 [State] 节点。

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

条件属性

你可以将此属性用于可视化条目中的 if-else 逻辑。

如果 _Myptr 成员不为空,则条件的计算结果为 false,第二个 DisplayString 元素显示。

XML
<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 特性

例如,在下面的 Natvis std::vector 规范中,simple 视图不显示 [size][capacity] 项。

XML
<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 属性。

Version 元素

Version 元素有助于避免名称冲突、减少无意间的不匹配,还允许在不同的类型版本中使用不同的可视化效果。

如果某个由不同模块使用的公共头文件定义了一个类型,则只有当该类型位于指定的模块版本中时,版本化的可视化效果才会显示。

在下面的示例中,可视化效果只适用于在 DirectUI::Border 版本 1.0 到 1.5 中找到的 Windows.UI.Xaml.dll 类型。

XML
<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>

不支持通配符。

不允许使用路径名。

DisplayString 元素

例如,以下 DisplayString 条目:

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

表示 CPoint 类型的变量显示如下图所示:

该示例还介绍了如何用双层大括号({{}})对大括号进行转义。

备注

所有其他可视化元素只接受调试器可以计算的表达式。

StringView 元素

例如,假设 ATL::CStringT 类型有以下可视化效果:

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

CStringT 对象将显示在一个变量窗口中,如下例所示:

添加 StringView 元素会告诉调试器,它可以将值显示为文本可视化。

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

有关详细信息,请参阅 C++ 中的格式说明符。

Expand 元素

Expand 节点接受用于定义子元素的子节点列表。

  • 如果未在可视化条目中指定 Expand 节点,子项将使用默认的展开规则。

  • 如果指定的 Expand 节点下面没有子节点,类型就无法在调试器窗口中展开。

Item 展开

例如,一个包含 CRecttopleftright 字段的 bottom 类具有以下可视化条目:

XML
<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 类型如下例所示:

调试器将计算 WidthHeight 元素中指定的表达式,然后在变量窗口的值列中显示值。

默认展开会为基类创建一个子树,并将基类的所有数据成员以子项的形式列出。

备注

如果项元素的表达式指向复杂类型,则项节点本身是可展开的。

Size

std::vector 的可视化效果是一个很好的示例:

XML
<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 在变量窗口中展开时显示其自身的元素:

ArrayItems 节点必须具有:

  • 用于使调试器了解数组长度的 Size 表达式(必须计算为整数)。
  • 一个 ValuePointer 表达式,指向第一个元素(必须为非 void* 元素类型的指针)。

Visual Studio 随附的 .Natvis 文件中提供了示例。

备注

可以使用 [] 运算符(例如 vector[i])以及任何使用了 ArrayItems 的一维数组可视化效果,即使该类型本身(例如 CATLArray)不允许使用此运算符。

在这种情况下,调试器需要稍微详细地显示子元素:

XML
<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 指定数组是采用行优先顺序还是列优先顺序。
  • Rank 指定数组的秩。
  • 在前面的示例中,表达式 _M_extent.M_base[0] 应为第0个维度指定长度,_M_extent._M_base[1] 为1,依此类推。

下面是调试器窗口中显示的一个二维 Concurrency::array 对象:

IndexListItems 展开

下面是 IndexListItems 节点的可视化处理:

XML
<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 个元素的完整表达式。

备注

可以使用 [] 运算符(例如 vector[i])以及任何使用了 IndexListItems 的一维数组可视化效果,即使该类型本身(例如 CATLArray)不允许使用此运算符。

LinkedListItems 展开

以下 CAtlList 类型的可视化效果使用 LinkedListItems

XML
<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>

HeadPointer 指向第一个元素, NextPointer 引用下一个元素,而 ValueNode 引用项的值。

m_pNextm_elementCNode 类(而不是 CAtlList 类)的字段。

ValueNode 可以保留为空或使用 this 来引用 LinkedListItems 节点本身。

CustomListItems 展开

使用 CustomListItems 来可视化数据结构,这些数据结构可以使用 C++ 表达式进行所有运算,但不太适合 ArrayItemsIndexListItemsLinkedListItems 模式。

不能使用 Exec 来计算函数( C++表达式计算器支持的调试器内部函数除外)。

下面的 CAtlMap 可视化工具是一个很好的例子,其中的 CustomListItems 用得很恰当。

XML
<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 节点的 std::map 类型的可视化效果:

XML
<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>

ValueNode 可以保留为空或使用 this 来引用 TreeItems 节点本身。

ExpandedItem 展开

调试器将计算指定的表达式,并将结果的子节点附加到该可视化类型的子列表中。

例如,智能指针类型 auto_ptr<vector<int>> 通常显示为:

通过添加 ExpandedItem 元素,就可以从层次结构中去除 _Myptr 变量并直接查看矢量元素:

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

CFrameworkElement 节点的可视化会将基 ExpandedItem 类的属性附加到 CPanel 类的子列表中,而不是重复这些属性。

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

使用nd格式说明符指示调试器使用基类可视化,如果基类没有可视化效果,则使用默认扩展。

Synthetic Item 展开

在下面的示例中, Concurrency::array 类型的可视化效果使用 Synthetic 节点向用户显示诊断消息:

XML
<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>

HResult 元素

HRDescription 元素包含要显示在调试器窗口中的信息。

XML

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

UIVisualizer 元素

.Natvis 文件包含插件的注册信息,例如名称、所公开服务的 GUID 以及它可以直观显示的类型。

下面是 UIVisualizer 元素的示例:

XML
<?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>
  • 在上面的示例中,同一个可视化工具服务提供了两个可视化工具。

  • 例如:

例如,下面的 std::vector 类型条目引用的是前一个示例中的 UIVisualizer

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

你可以在用于查看内存中位图的图像监视扩展中查看 UIVisualizer 的示例。

CustomVisualizer 元素

有关编写 VSIX 扩展的更多信息,请参阅 Visual Studio SDK。

自定义可视化工具有权访问所有的调试器扩展性 API,因此可以查询和修改调试对象进程,也可以与 Visual Studio 的其他部分通信。

可以在 Condition 元素上使用 IncludeViewExcludeViewCustomVisualizer 属性。

限制

Natvis 自定义项适用于类和结构,但不能使用 typedef。

mydoublearray, [100],这将显示前100个元素。

相关文章: