Create custom views of C++ objects in the debugger using the Natvis framework

Applies to: yesVisual Studio noVisual Studio for Mac

The Visual Studio Natvis framework customizes the way native types appear in debugger variable windows, such equally the Locals and Watch windows, and in DataTips. Natvis visualizations can aid brand the types yous create more than visible during debugging.

Natvis replaces the autoexp.dat file in earlier versions of Visual Studio with XML syntax, better diagnostics, versioning, and multiple file support.

Notation

Natvis customizations work with classes and structs, just not typedefs.

Natvis visualizations

You apply the Natvis framework to create visualization rules for the types you create, and so that developers can encounter them more easily during debugging.

For example, the post-obit illustration shows a variable of type Windows::UI::Xaml::Controls::TextBox in a debugger window without any custom visualizations applied.

TextBox default visualization

The highlighted row shows the Text holding of the TextBox class. The complex class bureaucracy makes information technology difficult to discover this property. The debugger doesn't know how to interpret the custom string type, so yous can't see the string held inside the textbox.

The same TextBox looks much simpler in the variable window when Natvis custom visualizer rules are applied. The important members of the grade appear together, and the debugger shows the underlying string value of the custom cord type.

TextBox data using visualizer

Use .natvis files in C++ projects

Natvis uses .natvis files to specify visualization rules. A .natvis file is an XML file with a .natvis extension. The Natvis schema is defined in <VS Installation Folder>\Xml\Schemas\1033\natvis.xsd.

The basic structure of a .natvis file is i or more than Blazon elements representing visualization entries. The fully qualified proper name of each Type element is specified in its Name aspect.

              <?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 provides some .natvis files in the <VS Installation Binder>\Common7\Packages\Debugger\Visualizers binder. These files have visualization rules for many common types, and can serve as examples for writing visualizations for new types.

Add a .natvis file to a C++ project

You can add a .natvis file to any C++ project.

To add a new .natvis file:

  1. Select the C++ project node in Solution Explorer, and select Project > Add new item, or right-click the project and select Add together > New item.

  2. In the Add New Detail dialog, select Visual C++ > Utility > Debugger visualization file (.natvis).

  3. Name the file, and select Add.

    The new file is added to Solution Explorer, and opens in the Visual Studio document pane.

The Visual Studio debugger loads .natvis files in C++ projects automatically, and past default, also includes them in the .pdb file when the project builds. If you lot debug the built app, the debugger loads the .natvis file from the .pdb file, even if y'all don't have the project open. If yous don't desire the .natvis file included in the .pdb, you lot can exclude it from the built .pdb file.

To exclude a .natvis file from a .pdb:

  1. Select the .natvis file in Solution Explorer, and select the Properties icon, or correct-click the file and select Properties.

  2. Drop down the arrow side by side to Excluded From Build and select Yes, and then select OK.

Note

For debugging executable projects, use the solution items to add any .natvis files that are not in the .pdb, since at that place is no C++ project available.

Note

Natvis rules loaded from a .pdb apply only to the types in the modules that the .pdb refers to. For case, if Module1.pdb has a Natvis entry for a type named Test, information technology just applies to the Examination class in Module1.dll. If some other module also defines a class named Test, the Module1.pdb Natvis entry does not utilize to information technology.

To install and annals a .natvis file via a VSIX package:

A VSIX package can install and register .natvis files. No matter where are they installed, all registered .natvis files are automatically picked upward during debugging.

  1. Include the .natvis file in the VSIX bundle. For instance, for the following project file:

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

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

Natvis file locations

You tin can add .natvis files to your user directory or to a system directory, if you want them to employ to multiple projects.

The .natvis files are evaluated in the following order:

  1. Whatever .natvis files that are embedded in a .pdb you're debugging, unless a file of the same name exists in the loaded project.

  2. Any .natvis files that are in a loaded C++ project or height-level solution. This group includes all loaded C++ projects, including class libraries, but not projects in other languages.

  3. Any .natvis files installed and registered via a VSIX packet.

  1. The user-specific Natvis directory (for example, %USERPROFILE%\Documents\Visual Studio 2022\Visualizers).
  1. The user-specific Natvis directory (for example, %USERPROFILE%\Documents\Visual Studio 2019\Visualizers).
  1. The user-specific Natvis directory (for case, %USERPROFILE%\Documents\Visual Studio 2017\Visualizers).
  1. The system-broad Natvis directory (<VS Installation Folder>\Common7\Packages\Debugger\Visualizers). This directory has the .natvis files that are installed with Visual Studio. If you have ambassador permissions, yous can add files to this directory.

Modify .natvis files while debugging

You tin can modify a .natvis file in the IDE while debugging its projection. Open the file in the same case of Visual Studio y'all're debugging with, change information technology, and save it. Equally before long as the file is saved, the Watch and Locals windows update to reflect the change.

You can as well add or delete .natvis files in a solution that you're debugging, and Visual Studio adds or removes the relevant visualizations.

Y'all tin can't update .natvis files that are embedded in .pdb files while you're debugging.

If you modify the .natvis file outside of Visual Studio, the changes don't accept issue automatically. To update the debugger windows, y'all tin reevaluate the .natvisreload command in the Immediate window. Then the changes accept effect without restarting the debugging session.

Also use the .natvisreload command to upgrade the .natvis file to a newer version. For case, the .natvis file may be checked into source control, and y'all want to option up recent changes that somebody else fabricated.

Expressions and formatting

Natvis visualizations use C++ expressions to specify the data items to display. In improver to the enhancements and limitations of C++ expressions in the debugger, which are described in Context operator (C++), exist enlightened of the following:

  • Natvis expressions are evaluated in the context of the object being visualized, not the current stack frame. For example, x in a Natvis expression refers to the field named x in the object existence visualized, not to a local variable named x in the electric current function. You tin't access local variables in Natvis expressions, although you lot tin access global variables.

  • Natvis expressions don't allow function evaluation or side furnishings. Function calls and assignment operators are ignored. Considering debugger intrinsic functions are side-effect complimentary, they may exist freely called from any Natvis expression, fifty-fifty though other part calls are disallowed.

  • To control how an expression displays, you tin employ any of the format specifiers described in Format specifiers in C++. Format specifiers are ignored when the entry is used internally by Natvis, such every bit the Size expression in a ArrayItems expansion.

Note

Because the natvis certificate is XML, your expressions cannot directly utilise the ampersand, greater than, less than, or shift operators. You must escape these characters in both the particular torso and the condition statements. For case:
<Item Name="HiByte">(byte)(_flags &gt;&gt; 24),x</Item>
<Item Name="HiByteStatus" Condition="(_flags &amp; 0xFF000000) == 0">"None"</Detail>
<Item Name="HiByteStatus" Condition="(_flags &amp; 0xFF000000) != 0">"Some"</Item>

Natvis views

You can define different Natvis views to display types in different ways. For example, here is a visualization of std::vector that defines a simplified view named simple. 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.

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

In the Sentry window, employ the ,view format specifier to specify an alternate view. The simple view appears as vec,view(simple):

Watch window with simple view

Natvis errors

When the debugger encounters errors in a visualization entry, it ignores them. Information technology either displays the blazon in its raw course, or picks another suitable visualization. You tin employ Natvis diagnostics to sympathise why the debugger ignored a visualization entry, and to see underlying syntax and parse errors.

To turn on Natvis diagnostics:

  • Nether Tools > Options (or Debug > Options) > Debugging > Output Window, set Natvis diagnostic messages (C++ just) to Mistake, Warning, or Verbose, and and so select OK.

The errors appear in the Output window.

Natvis syntax reference

AutoVisualizer element

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>                          

The AutoVisualizer element can accept Type, HResult, UIVisualizer, and CustomVisualizer children.

Blazon element

A basic Type looks similar this example:

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

The Type chemical element specifies:

  1. What type the visualization should be used for (the Proper noun attribute).

  2. What the value of an object of that type should wait similar (the DisplayString element).

  3. What the members of the blazon should look like when the user expands the type in a variable window (the Expand node).

Templated classes

The Name attribute of the Type chemical element accepts an asterisk * as a wildcard character that can be used for templated class names.

In the following instance, the aforementioned visualization is used whether the object is a CAtlArray<int> or a CAtlArray<float>. If in that location'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>                          

Yous can reference template parameters in the visualization entry by using macros $T1, $T2, and then along. To discover examples of these macros, run into 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

The optional Inheritable attribute specifies whether a visualization applies only to a base type, or to a base type and all derived types. The default value of Inheritable is true.

In the post-obit instance, the visualization applies but to the BaseClass type:

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

Priority aspect

The optional Priority attribute specifies the order in which to utilize alternate definitions, if a definition fails to parse. The possible values of Priority are: Depression, MediumLow,Medium, MediumHigh, and High. The default value is Medium. The Priority attribute distinguishes but amongst priorities inside the same .natvis file.

The following example first parses the entry that matches the 2015 STL. 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> </Blazon>  <!-- VC 2015 --> <Type Proper noun="std::reference_wrapper&lt;*&gt;">     <DisplayString>{*_Ptr}</DisplayString>     <Expand>         <Item Name="[ptr]">_Ptr</Item>     </Expand> </Type>                          

Optional attribute

You tin put an Optional attribute on any node. If a subexpression inside an optional node fails to parse, the debugger ignores that node, just applies the remainder of the Type rules. In the following type, [State] is not-optional, only [Exception] is optional. If MyNamespace::MyClass has a field named _M_exceptionHolder, both the [State] node and the [Exception] node appear, only if in that location's no _M_exceptionHolder field, only the [State] node appears.

              <Blazon Proper name="MyNamespace::MyClass">     <Expand>       <Item Name="[State]">_M_State</Particular>       <Detail Name="[Exception]" Optional="true">_M_exceptionHolder</Item>     </Expand> </Blazon>                          

Condition attribute

The optional Condition attribute is bachelor for many visualization elements, and specifies when to apply a visualization rule. If the expression inside the condition attribute resolves to false, the visualization rule doesn't utilise. If information technology evaluates to true, or there is no Status attribute, the visualization applies. You can use this attribute for if-else logic in the visualization entries.

For example, the post-obit visualization has two DisplayString elements for a smart pointer type. When the _Myptr member is empty, the condition of the showtime DisplayString element resolves to true, and so that form displays. When the _Myptr fellow member is not empty, the condition evaluates to imitation, and the 2d DisplayString element displays.

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

IncludeView and ExcludeView attributes

The IncludeView and ExcludeView attributes specify elements to display or not display in specific views. For instance, 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>     <Aggrandize>         <Detail Proper name="[size]" ExcludeView="unproblematic">_Mylast - _Myfirst</Item>         <Item Name="[capacity]" ExcludeView="unproblematic">_Myend - _Myfirst</Item>         <ArrayItems>             <Size>_Mylast - _Myfirst</Size>             <ValuePointer>_Myfirst</ValuePointer>         </ArrayItems>     </Expand> </Blazon>                          

You can utilize the IncludeView and ExcludeView attributes on types and on private members.

Version element

The Version element scopes a visualization entry to a specific module and version. The Version element helps avert name collisions, reduces inadvertent mismatches, and allows different visualizations for different blazon versions.

If a common header file that is used by dissimilar modules defines a type, the versioned visualization appears only when the type is in the specified module version.

In the following instance, the visualization is applicative only for the DirectUI::Border blazon 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="i.5"/>   <DisplayString>{{Name = {*(m_pDO->m_pstrName)}}}</DisplayString>   <Expand>     <ExpandedItem>*(CBorder*)(m_pDO)</ExpandedItem>   </Aggrandize> </Type>                          

Y'all don't need both Min and Max. They are optional attributes. No wildcard characters are supported.

The Proper noun aspect is in the format filename.ext, such every bit howdy.exe or some.dll. No path names are allowed.

DisplayString element

The DisplayString element specifies a string to prove as the value of a variable. It accepts arbitrary strings mixed with expressions. Everything within curly braces is interpreted as an expression. For instance, the post-obit DisplayString entry:

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

Means that variables of blazon CPoint brandish as in this illustration:

Use a DisplayString element

In the DisplayString expression, x and y, which are members of CPoint, are within curly braces, and then their values are evaluated. The instance too shows how you can escape a curly brace by using double curly braces ( {{ or }} ).

Note

The DisplayString chemical element is the only element that accepts arbitrary strings and curly brace syntax. All other visualization elements have only expressions that the debugger can evaluate.

StringView element

The StringView chemical element defines a value that the debugger tin can transport to the built-in text visualizer. For instance, given the post-obit visualization for the ATL::CStringT type:

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

The CStringT object displays in a variable window like this instance:

CStringT DisplayString element

Adding a StringView chemical 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>                          

During debugging, you can select the magnifying glass icon side by side to the variable, and then select Text Visualizer to display the string that m_pszData points to.

CStringT data with StringView visualizer

The expression {m_pszData,su} includes a C++ format specifier su, to display the value as a Unicode cord. For more information, see Format specifiers in C++.

Expand chemical element

The optional Expand node customizes the children of a visualized blazon when y'all expand the type in a variable window. The Expand node accepts a listing of child nodes that ascertain the kid elements.

  • If an Aggrandize node isn't specified in a visualization entry, the children use the default expansion rules.

  • If an Expand node is specified with no kid nodes under it, the blazon isn't expandable in the debugger windows.

Detail expansion

The Detail element is the most bones and common chemical element in an Expand node. Item defines a single child element. For example, a CRect form with fields top, left, right, and lesser has the following visualization entry:

              <Type Name="CRect">   <DisplayString>{{elevation={peak} lesser={bottom} left={left} right={correct}}}</DisplayString>   <Expand>     <Item Proper name="Width">right - left</Item>     <Detail Proper name="Top">bottom - height</Item>   </Expand> </Type>                          

In the debugger window, the CRect type looks like this example:

CRect with Item element expansion

The debugger evaluates the expressions specified in the Width and Height elements, and shows the values in the Value cavalcade of the variable window.

The debugger automatically creates the [Raw View] node for every custom expansion. The preceding screenshot displays the [Raw View] node expanded, to evidence 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.

Annotation

If the expression of the item element points to a complex blazon, the Item node itself is expandable.

ArrayItems expansion

Use the ArrayItems node to take the Visual Studio debugger translate the type as an array and brandish its individual elements. The visualization for std::vector is a expert example:

              <Type Proper noun="std::vector&lt;*&gt;">   <DisplayString>{{size = {_Mylast - _Myfirst}}}</DisplayString>   <Aggrandize>     <Particular Name="[size]">_Mylast - _Myfirst</Item>     <Item Name="[chapters]">(_Myend - _Myfirst)</Item>     <ArrayItems>       <Size>_Mylast - _Myfirst</Size>       <ValuePointer>_Myfirst</ValuePointer>     </ArrayItems>   </Aggrandize> </Blazon>                          

A std::vector shows its private elements when expanded in the variable window:

std::vector using ArrayItems expansion

The ArrayItems node must have:

  • A Size expression (which must evaluate to an integer) for the debugger to understand the length of the array.
  • A ValuePointer expression that points to the first chemical element (which must be a pointer of an chemical element blazon that is not void*).

The default value of the array lower bound is 0. To override the value, use a LowerBound element. The .natvis files shipped with Visual Studio take examples.

Note

You can apply the [] operator, for example vector[i], with whatever unmarried-dimensional array visualization that uses ArrayItems, fifty-fifty if the blazon itself (for example CATLArray) does not permit this operator.

You can too specify multi-dimensional arrays. In that example, the debugger needs slightly more than information to properly display child elements:

              <Type Name="Concurrency::array&lt;*,*&gt;">   <DisplayString>extent = {_M_extent}</DisplayString>   <Aggrandize>     <Item Name="extent">_M_extent</Particular>     <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>                          
  • Management specifies whether the array is in row-major or column-major order.
  • Rank specifies the rank of the array.
  • The Size element accepts the implicit $i parameter, which it substitutes with the dimension index to find the length of the assortment in that dimension. In the previous example, the expression _M_extent.M_base[0] should requite the length of the 0th dimension, _M_extent._M_base[i] the 1st, and so on.

Hither's how a two-dimensional Concurrency::array object looks in the debugger window:

Two-dimensional array with ArrayItems expansion

IndexListItems expansion

You lot tin utilise ArrayItems expansion merely if the array elements are laid out contiguously in memory. The debugger gets to the adjacent chemical element past but incrementing its pointer. If you need to manipulate the index to the value node, utilize IndexListItems nodes. Here's a visualization with an IndexListItems node:

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

The only difference between ArrayItems and IndexListItems is the ValueNode, which expects the full expression to the ith element with the implicit $i parameter.

Notation

You can use the [] operator, for example vector[i], with any single-dimensional assortment visualization that uses IndexListItems, even if the type itself (for example CATLArray) does not let this operator.

LinkedListItems expansion

If the visualized blazon represents a linked list, the debugger can brandish its children by using a LinkedListItems node. The following visualization for the CAtlList type uses LinkedListItems:

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

The Size element refers to the length of the list. HeadPointer points to the first chemical element, NextPointer refers to the next element, and ValueNode refers to the value of the item.

The debugger evaluates the NextPointer and ValueNode expressions in the context of the LinkedListItems node chemical element, not the parent list type. In the preceding example, CAtlList has a CNode course (found in atlcoll.h) that is a node of the linked list. m_pNext and m_element are fields of that CNode grade, not of the CAtlList course.

ValueNode can be left empty, or use this to refer to the LinkedListItems node itself.

CustomListItems expansion

The CustomListItems expansion allows you lot to write custom logic for traversing a data structure such as a hashtable. Use CustomListItems to visualize information structures that can employ C++ expressions for everything you lot demand to evaluate, merely don't quite fit the mold for ArrayItems, IndexListItems, or LinkedListItems.

You can use Exec to execute code inside of a CustomListItems expansion, using the variables and objects defined in the expansion. You can use logical operators, arithmetic operators, and assignment operators with Exec. You can't apply Exec to evaluate functions, except for debugger intrinsic functions supported by the C++ expression evaluator.

The post-obit visualizer for CAtlMap is an excellent case where CustomListItems is appropriate.

              <Type Proper noun="ATL::CAtlMap&lt;*,*,*,*&gt;">     <AlternativeType Proper name="ATL::CMapToInterface&lt;*,*,*&gt;"/>     <AlternativeType Proper noun="ATL::CMapToAutoPtr&lt;*,*,*&gt;"/>     <DisplayString>{{Count = {m_nElements}}}</DisplayString>     <Expand>       <CustomListItems MaxItemsPerView="5000" ExcludeView="Examination">         <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>             <Interruption Condition="iBucketIncrement == -one" />             <Exec>iBucket += iBucketIncrement</Exec>             <Exec>pBucket = m_ppBins[iBucket]</Exec>           </If>           <Detail>pBucket,na</Item>           <Exec>pBucket = pBucket->m_pNext</Exec>         </Loop>       </CustomListItems>     </Aggrandize> </Blazon>                          

TreeItems expansion

If the visualized blazon represents a tree, the debugger can walk the tree and brandish its children by using a TreeItems node. Here'southward the visualization for the std::map type using a TreeItems node:

              <Blazon Proper noun="std::map&lt;*&gt;">   <DisplayString>{{size = {_Mysize}}}</DisplayString>   <Aggrandize>     <Item Proper noun="[size]">_Mysize</Item>     <Detail Proper noun="[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>                          

The syntax is similar to the LinkedListItems node. LeftPointer, RightPointer, and ValueNode are evaluated nether the context of the tree node course. ValueNode can exist left empty or use this to refer to the TreeItems node itself.

ExpandedItem expansion

The ExpandedItem element generates an aggregated child view by displaying backdrop of base of operations classes or data members every bit if they were children of the visualized blazon. The debugger evaluates the specified expression, and appends the child nodes of the effect to the kid list of the visualized blazon.

For case, the smart pointer blazon auto_ptr<vector<int>> typically displays as:

auto_ptr<vector<int>> default expansion

To meet the values of the vector, you accept to drill down two levels in the variable window, passing through the _Myptr member. 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> </Blazon>                          

auto_ptr<vector<int>> ExpandedItem expansion

The following case shows how to aggregate properties from the base of operations class in a derived grade. Suppose the CPanel grade derives from CFrameworkElement. Instead of repeating the properties that come from the base CFrameworkElement class, the ExpandedItem node visualization appends those backdrop to the child list of the CPanel class.

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

The nd format specifier, which turns off visualization matching for the derived class, is necessary hither. Otherwise, the expression *(CFrameworkElement*)this would cause the CPanel visualization to be applied over again, because the default visualization blazon matching rules consider it the most appropriate 1. 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.

Constructed item expansion

While the ExpandedItem element provides a flatter view of data by eliminating hierarchies, the Constructed node does the opposite. It allows y'all to create an artificial child element that isn't a result of an expression. The artificial chemical element tin can have child elements of its ain. In the following example, the visualization for the Concurrency::array blazon uses a Constructed node to prove a diagnostic message to the user:

              <Type Proper noun="Concurrency::assortment&lt;*,*&gt;">   <DisplayString>extent = {_M_extent}</DisplayString>   <Aggrandize>     <Item Proper noun="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 Proper name="Assortment" Status="_M_buffer_descriptor._M_data_ptr == 0">       <DisplayString>Assortment members tin can be viewed merely under the GPU debugger</DisplayString>     </Synthetic>   </Aggrandize> </Type>                          

Concurrency::Array with Synthetic element expansion

HResult element

The HResult chemical element lets you lot customize the information shown for an HRESULT in debugger windows. The HRValue element must contain the 32-bit value of the HRESULT that is to be customized. The HRDescription element contains the information to testify in the debugger window.

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

UIVisualizer chemical element

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 mode consistent with its data type. The visualizer plug-in must be authored equally a VSPackage, and must betrayal a service that the debugger tin can eat. The .natvis file contains registration information for the plug-in, such equally its name, the GUID of the exposed service, and the types it can visualize.

Here's an example of a UIVisualizer element:

              <?xml version="i.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>                          
  • A ServiceId - Id attribute pair identifies a UIVisualizer. The ServiceId is the GUID of the service the visualizer package exposes. 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.

  • The MenuName attribute defines a visualizer proper name to brandish in the drop-downward adjacent to the magnifying glass icon in the debugger. For instance:

    UIVisualizer menu shortcut menu

Each blazon defined in the .natvis file must explicitly list whatever UI visualizers that can display it. The debugger matches the visualizer references in the type entries with the registered visualizers. For instance, the following blazon 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" /> </Blazon>                          

Yous tin see an case of a UIVisualizer in the Image Sentinel extension used to view in-memory bitmaps.

CustomVisualizer element

CustomVisualizer is an extensibility signal that specifies a VSIX extension that you lot write to control visualizations in Visual Studio code. For more information about writing VSIX extensions, come across the Visual Studio SDK.

It's a lot more work to write a custom visualizer than an XML Natvis definition, simply you're free from constraints about what Natvis does or doesn't support. Custom visualizers have access to the full gear up of debugger extensibility APIs, which can query and modify the debuggee process or communicate with other parts of Visual Studio.

Yous can use the Status, IncludeView, and ExcludeView attributes on CustomVisualizer elements.

Limitations

Natvis customizations work with classes and structs, simply non typedefs.

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 instance. For example, if you use double* mydoublearray in your lawmaking, so you tin can apply an array format specifier in the debugger's Sentry window, such as the expression mydoublearray, [100], which shows the start 100 elements.