Delen via


Aangepaste weergaven van C++-objecten maken in het foutopsporingsprogramma met behulp van het Natvis-framework

Het Visual Studio Natvis-framework past de manier aan waarop systeemeigen typen worden weergegeven in vensters voor foutopsporingsprogrammavariabelen, zoals de Locals en Watch-vensters, en in DataTips. Natvis-visualisaties kunnen helpen de typen die u maakt beter zichtbaar te maken tijdens foutopsporing.

Natvis vervangt het autoexp.dat-bestand in eerdere versies van Visual Studio door XML-syntaxis, betere diagnose, versiebeheer en ondersteuning voor meerdere bestanden.

Notitie

Natvis-aanpassingen werken met klassen en structs, maar niet met typedefs.

Natvis-visualisaties

U gebruikt het Natvis-framework om visualisatieregels te maken voor de typen die u maakt, zodat ontwikkelaars deze gemakkelijker kunnen zien tijdens foutopsporing.

In de volgende afbeelding ziet u bijvoorbeeld een variabele van het type Windows::UI::XAML::Controls::TextBox in een foutopsporingsprogrammavenster zonder dat aangepaste visualisaties zijn toegepast.

Tekstvak standaardvisualisatie

In de gemarkeerde rij wordt de eigenschap Text van de klasse TextBox weergegeven. De complexe klassehiërarchie maakt het moeilijk om deze eigenschap te vinden. Het foutopsporingsprogramma weet niet hoe u het aangepaste tekenreekstype interpreteert, zodat u de tekenreeks niet in het tekstvak kunt zien.

Dezelfde TextBox ziet er veel eenvoudiger uit in het variabelevenster wanneer aangepaste visualisatieregels van Natvis worden toegepast. De belangrijke leden van de klasse worden samen weergegeven en het foutopsporingsprogramma toont de onderliggende tekenreekswaarde van het aangepaste tekenreekstype.

TextBox-gegevens met visualizer

.natvis-bestanden gebruiken in C++-projecten

Natvis maakt gebruik van .natvis bestanden om visualisatieregels op te geven. Een .natvis--bestand is een XML-bestand met een .natvis--extensie. Het Natvis-schema wordt gedefinieerd in <VS-installatiemap>\Xml\Schemas\1033\natvis.xsd.

De basisstructuur van een bestand .natvis is een of meer Type elementen die visualisatievermeldingen vertegenwoordigen. De volledig gekwalificeerde naam van elk Type element wordt opgegeven in het kenmerk Name.

<?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 biedt enkele .natvis--bestanden in de map <VS-installatiemap>\Common7\Packages\Debugger\Visualizers map. Deze bestanden hebben visualisatieregels voor veel algemene typen en kunnen fungeren als voorbeelden voor het schrijven van visualisaties voor nieuwe typen.

Een NATVIS-bestand toevoegen aan een C++-project

U kunt een .natvis--bestand toevoegen aan een C++-project.

Voeg een nieuw .natvis- bestand toe:

  1. Selecteer het C++-projectknooppunt in Solution Explorer-en selecteer Project>Nieuw item toevoegen, of klik met de rechtermuisknop op het project en selecteer Toevoegen>Nieuw item.

    Als u niet alle itemsjablonen ziet, kiest u Alle sjablonen weergeven.

  2. Selecteer in het dialoogvenster Add New ItemVisual C++>Utility>Het visualisatiebestand voor foutopsporingsprogramma (.natvis).

  3. Geef het bestand een naam en selecteer Toevoegen.

    Het nieuwe bestand wordt toegevoegd aan Solution Explorer-en wordt geopend in het documentvenster van Visual Studio.

Het foutopsporingsprogramma van Visual Studio laadt automatisch .natvis--bestanden in C++-projecten en bevat deze standaard ook in het .pdb--bestand wanneer het project wordt gebouwd. Als u fouten in de ingebouwde app opslaadt, laadt het foutopsporingsprogramma het .natvis--bestand uit het .pdb--bestand, zelfs als u het project niet hebt geopend. Als u het bestand .natvis niet wilt opnemen in de .pdb-, kunt u het uitsluiten van het ingebouwde .pdb--bestand.

Een .natvis--bestand uitsluiten van een .pdb-:

  1. Selecteer het .natvis--bestand in Solution Exploreren selecteer het pictogram Eigenschappen of klik met de rechtermuisknop op het bestand en selecteer Eigenschappen.

  2. Gebruik de vervolgkeuzelijst, klik op de pijl naast Uitgesloten van build en selecteer Ja, en selecteer vervolgens OK.

Notitie

Voor het opsporen van fouten in uitvoerbare projecten gebruikt u de oplossingsitems om alle .natvis--bestanden toe te voegen die zich niet in de .pdb-bevinden, omdat er geen C++-project beschikbaar is.

Notitie

Natvis-regels die zijn geladen vanuit een .pdb- zijn alleen van toepassing op de typen in de modules waarnaar de .pdb- verwijst. Als Module1.pdb- bijvoorbeeld een Natvis-vermelding heeft voor een type met de naam Test, is dit alleen van toepassing op de klasse Test in Module1.dll. Als een andere module ook een klasse met de naam Testdefinieert, is de Module1.pdb- Natvis-vermelding niet van toepassing.

Een .natvis--bestand installeren en registreren via een VSIX-pakket:

Een VSIX-pakket kan .natvis--bestanden installeren en registreren. Ongeacht waar ze zijn geïnstalleerd, worden alle geregistreerde .natvis--bestanden automatisch opgehaald tijdens foutopsporing.

  1. Neem het .natvis--bestand op in het VSIX-pakket. Bijvoorbeeld voor het volgende projectbestand:

    <?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. Registreer het bestand .natvis in het bestand source.extension.vsixmanifest:

    <?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-bestandslocaties

U kunt .natvis--bestanden toevoegen aan uw gebruikersmap of aan een systeemmap, als u wilt dat ze van toepassing zijn op meerdere projecten.

De .natvis--bestanden worden in de volgende volgorde geëvalueerd:

  1. Alle .natvis--bestanden die zijn ingesloten in een .pdb- terwijl u aan het debuggen bent, tenzij er een bestand met dezelfde naam bestaat in het geladen project.

  2. Alle .natvis- bestanden die zich in een geladen C++-project of een oplossing op het hoogste niveau bevinden. Deze groep bevat alle geladen C++-projecten, waaronder klassebibliotheken, maar geen projecten in andere talen.

  3. Alle .natvis--bestanden die zijn geïnstalleerd en geregistreerd via een VSIX-pakket.

  1. De gebruikersspecifieke Natvis-map (bijvoorbeeld %USERPROFILE%\Documents\Visual Studio 2022\Visualizers).
  1. De gebruikersspecifieke Natvis-map (bijvoorbeeld %USERPROFILE%\Documents\Visual Studio 2019\Visualizers).
  1. De natvis-map voor het hele systeem (<Microsoft Visual Studio-installatiemap>\Common7\Packages\Debugger\Visualizers). Deze map bevat de .natvis--bestanden die zijn geïnstalleerd met Visual Studio. Als u beheerdersmachtigingen hebt, kunt u bestanden toevoegen aan deze map.

.natvis-bestanden wijzigen tijdens foutopsporing

U kunt een .natvis--bestand wijzigen in de IDE tijdens het opsporen van fouten in het project. Open het bestand in hetzelfde exemplaar van Visual Studio waarmee u fouten opspoort, wijzig het en sla het op. Zodra het bestand is opgeslagen, worden de Watch- en Locals-vensters bijgewerkt om de wijziging weer te geven.

U kunt ook .natvis--bestanden toevoegen of verwijderen in een oplossing die u aan het debuggen bent, en Visual Studio voegt de relevante visualisaties toe of verwijdert ze.

U kunt .natvis--bestanden die zijn ingesloten in .pdb bestanden niet bijwerken terwijl u foutopsporing uitvoert.

Als u het bestand .natvis buiten Visual Studio wijzigt, worden de wijzigingen niet automatisch doorgevoerd. Als u de foutopsporingsprogrammavensters wilt bijwerken, kunt u de opdracht .natvisreload opnieuw uitvoeren in het venster Direct. Vervolgens worden de wijzigingen van kracht zonder de foutopsporingssessie opnieuw op te starten.

Gebruik ook de opdracht .natvisreload om het .natvis--bestand bij te werken naar een nieuwere versie. Het bestand .natvis kan bijvoorbeeld worden ingecheckt bij broncodebeheer en u wilt recente wijzigingen ophalen die iemand anders heeft aangebracht.

Expressies en opmaak

Natvis-visualisaties maken gebruik van C++-expressies om de gegevensitems op te geven die moeten worden weergegeven. Naast de verbeteringen en beperkingen van C++-expressies in het foutopsporingsprogramma, die worden beschreven in Contextoperator (C++), moet u rekening houden met het volgende:

  • Natvis-expressies worden geëvalueerd in de context van het object dat wordt gevisualiseerd, niet het huidige stackframe. x in een Natvis-expressie verwijst bijvoorbeeld naar het veld met de naam x in het object dat wordt gevisualiseerd, niet naar een lokale variabele met de naam x in de huidige functie. U hebt geen toegang tot lokale variabelen in Natvis-expressies, hoewel u toegang hebt tot globale variabelen.

  • Natvis-expressies staan functie-evaluatie of bijwerkingen niet toe. Functie-aanroepen en toewijzingsoperatoren worden genegeerd. Omdat intrinsieke functies van het foutopsporingsprogramma neveneffectvrij zijn, kunnen ze vrij worden aangeroepen vanuit een Natvis-expressie, ook al zijn andere functieaanroepen niet toegestaan.

  • Als u wilt bepalen hoe een expressie wordt weergegeven, kunt u een van de notatieaanduidingen gebruiken die worden beschreven in Opmaakaanduidingen in C++. Opmaakparameters worden genegeerd wanneer een element intern door Natvis wordt gebruikt, zoals de Size-expressie in een ArrayItems-uitbreiding.

Notitie

Omdat het Natvis-document XML is, kunnen uw expressies niet rechtstreeks gebruikmaken van het en-teken, groter dan, kleiner dan of shift-operatoren. U moet deze tekens in zowel de hoofdtekst van het item als de voorwaardeinstructies escapen. Bijvoorbeeld:
\<Item Name="HiByte"\>(byte)(_flags \&gt;\&gt; 24),x\</Item\>
\<Item Name="HiByteStatus" Condition="(_flags \&amp; 0xFF000000) == 0"\>"None"\</Item\>
\<Item Name="HiByteStatus" Condition="(_flags \&amp; 0xFF000000) != 0"\>"Some"\</Item\>

Natvis-weergaven

U kunt verschillende Natvis-weergaven definiëren om typen op verschillende manieren weer te geven. Hier ziet u bijvoorbeeld een visualisatie van std::vector waarmee een vereenvoudigde weergave met de naam simplewordt gedefinieerd. De DisplayString en de ArrayItems-elementen worden weergegeven in de standaardweergave en de simple weergave, terwijl de [size] en [capacity] items niet worden weergegeven in de simple weergave.

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

Gebruik in het venster Watch de opmaakspecificator ,view om een alternatieve weergave op te geven. De eenvoudige weergave wordt weergegeven als vec, view(simple):

Bekijkvenster met eenvoudige weergave

Natvis-fouten

Wanneer het foutopsporingsprogramma fouten in een visualisatievermelding tegenkomt, worden deze genegeerd. Het type wordt in de onbewerkte vorm weergegeven of er wordt een andere geschikte visualisatie gekozen. U kunt natvis-diagnostische gegevens gebruiken om te begrijpen waarom het foutopsporingsprogramma een visualisatievermelding heeft genegeerd en om onderliggende syntaxis en parseringsfouten te bekijken.

Diagnostische gegevens van Natvis inschakelen:

  • Onder Hulpmiddelen>opties (of Foutopsporing>opties) >Foutopsporing>uitvoervenster, stelt u Natvis diagnostische berichten (alleen C++) in op Fout, Waarschuwingof Uitgebreideen selecteer vervolgens OK.

De fouten worden weergegeven in het venster Uitvoer.

Natvis-syntaxisreferentie

De volgende elementen en kenmerken kunnen worden gebruikt in het Natvis-bestand.

AutoVisualizer-element

Het element AutoVisualizer is het hoofdknooppunt van het .natvis-bestand en bevat de naamruimte xmlns: kenmerk.

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

Het element AutoVisualizer kan Type, HResult, UIVisualizeren CustomVisualizer onderliggende elementen hebben.

Type element

Een eenvoudige Type ziet er als volgt uit:

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

Het element Type geeft het volgende op:

  1. Voor welk type de visualisatie moet worden gebruikt (het kenmerk Name).

  2. Hoe de waarde van een object van dat type eruit moet zien (het DisplayString element).

  3. Hoe de leden van het type eruit moeten zien wanneer de gebruiker het type in een variabelevenster uitvouwt (het knooppunt Expand).

Sjabloonklassen

Het kenmerk Name van het Type element accepteert een sterretje * als jokerteken dat kan worden gebruikt voor sjabloonklassenamen.

In het volgende voorbeeld wordt dezelfde visualisatie gebruikt of het object een CAtlArray<int> of een CAtlArray<float>is. Als er een specifieke visualisatievermelding is voor een CAtlArray<float>, heeft deze voorrang op de algemene vermelding.

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

U kunt verwijzen naar sjabloonparameters in de visualisatievermelding met behulp van macro's $T 1, $T 2 enzovoort. Zie de .natvis- bestanden die zijn verzonden met Visual Studio voor voorbeelden van deze macro's.

Type overeenkomende visualisatie

Als een visualisatievermelding niet kan worden gevalideerd, wordt de volgende beschikbare visualisatie gebruikt.

Overgenomen kenmerk

Het optionele kenmerk Inheritable geeft aan of een visualisatie alleen van toepassing is op een basistype of op een basistype en alle afgeleide typen. De standaardwaarde van Inheritable is true.

In het volgende voorbeeld is de visualisatie alleen van toepassing op het BaseClass type:

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

Prioriteitskenmerk

Het optionele kenmerk Priority geeft de volgorde aan waarin alternatieve definities moeten worden gebruikt, als een definitie niet kan worden geparseerd. De mogelijke waarden van Priority zijn: Low, MediumLow,Medium, MediumHighen High. De standaardwaarde is Medium. Het kenmerk Priority onderscheidt zich alleen van prioriteiten binnen hetzelfde .natvis--bestand.

In het volgende voorbeeld wordt eerst de vermelding geparseerd die overeenkomt met de STL van 2015. Als dit niet kan worden geparseerd, wordt de alternatieve vermelding gebruikt voor de 2013-versie van de 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>

Optioneel kenmerk

U kunt een Optional kenmerk op elk knooppunt plaatsen. Als een subexpressie in een optioneel knooppunt niet kan worden geparseerd, negeert het foutopsporingsprogramma dat knooppunt, maar past de rest van de Type regels toe. In het volgende type is [State] niet optioneel, maar [Exception] is optioneel. Als MyNamespace::MyClass een veld heeft met de naam _M_exceptionHolder, worden zowel het [State]-knooppunt als het [Exception]-knooppunt weergegeven, maar als er geen _M_exceptionHolder veld is, wordt alleen het [State] knooppunt weergegeven.

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

Voorwaardekenmerk

Het optionele kenmerk Condition is beschikbaar voor veel visualisatie-elementen en geeft aan wanneer een visualisatieregel moet worden gebruikt. Als de expressie in het voorwaardekenmerk wordt omgezet in false, is de visualisatieregel niet van toepassing. Als het resulteert in trueof als er geen Condition kenmerk is, is de visualisatie van toepassing. U kunt dit kenmerk gebruiken voor if-else-logica in de visualisatievermeldingen.

De volgende visualisatie bevat bijvoorbeeld twee DisplayString elementen voor een slim aanwijzertype. Wanneer het _Myptr lid leeg is, wordt de voorwaarde van het eerste DisplayString-element omgezet in true, zodat het formulier wordt weergegeven. Wanneer het _Myptr lid niet leeg is, resulteert de voorwaarde in falseen wordt het tweede DisplayString element weergegeven.

<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- en ExcludeView-kenmerken

De kenmerken IncludeView en ExcludeView geven elementen op die in bepaalde weergaven moeten worden weergegeven of niet. In de volgende Natvis-specificatie van std::vectorworden in de simple weergave bijvoorbeeld niet de [size]- en [capacity] items weergegeven.

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

U kunt de kenmerken IncludeView en ExcludeView voor typen en voor afzonderlijke leden gebruiken.

Versie-element

Met het Version-element wordt een visualisatie-item beperkt tot een specifieke module en versie. Het element Version helpt bij het voorkomen van naamconflicten, vermindert onbedoelde verschillen en maakt verschillende visualisaties voor verschillende typeversies mogelijk.

Als een algemeen headerbestand dat wordt gebruikt door verschillende modules een type definieert, wordt de versievisualisatie alleen weergegeven wanneer het type zich in de opgegeven moduleversie bevindt.

In het volgende voorbeeld is de visualisatie alleen van toepassing op het DirectUI::Border type dat in de Windows.UI.Xaml.dll van versie 1.0 tot en met 1.5 is gevonden.

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

U hebt niet zowel Min als Maxnodig. Dit zijn optionele kenmerken. Er worden geen jokertekens ondersteund.

Het kenmerk Name heeft de indeling bestandsnaam.ext-, zoals hello.exe of some.dll. Er zijn geen padnamen toegestaan.

DisplayString-element

Het element DisplayString geeft een tekenreeks op die moet worden weergegeven als de waarde van een variabele. Het accepteert willekeurige tekenreeksen die zijn gemengd met expressies. Alles binnen accolades wordt geïnterpreteerd als een expressie. Bijvoorbeeld de volgende DisplayString vermelding:

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

Betekent dat variabelen van het type CPoint worden weergegeven zoals in deze afbeelding:

Een DisplayString-element gebruiken

In de expressie DisplayString bevinden x en y, die lid zijn van CPoint, zich binnen accolades, waardoor hun waarden worden geëvalueerd. In het voorbeeld ziet u ook hoe u kunt ontsnappen aan een accolade door gebruik te maken van dubbele accolades ({{ of }}).

Notitie

Het DisplayString-element is het enige element dat willekeurige tekenreeksen en accoladesyntaxis accepteert. Alle andere visualisatie-elementen accepteren alleen expressies die het foutopsporingsprogramma kan evalueren.

Het element StringView

Het element StringView definieert een waarde die het foutopsporingsprogramma naar de ingebouwde tekstvisualr kan verzenden. Bijvoorbeeld, op basis van de volgende visualisatie voor het ATL::CStringT type:

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

Het CStringT-object wordt weergegeven in een variabelevenster zoals in dit voorbeeld:

CStringT DisplayString-element

Als u een StringView-element toevoegt, wordt aan het foutopsporingsprogramma aangegeven dat de waarde kan worden weergegeven als tekstvisualisatie.

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

Tijdens foutopsporing kunt u het vergrootglaspictogram naast de variabele selecteren en vervolgens Text Visualizer selecteren om de tekenreeks weer te geven waarnaar m_pszData verwijst.

CStringT-gegevens met StringView visualizer

De expressie {m_pszData,su} bevat een C++-indelingsaanduiding suom de waarde weer te geven als een Unicode-tekenreeks. Zie Opmaakaanduidingen in C++voor meer informatie.

Element uitvouwen

Met het optionele Expand-knooppunt worden de onderliggende elementen van een gevisualiseerd type aangepast wanneer u het type in een variabelevenster uitvouwt. Het Expand knooppunt accepteert een lijst met onderliggende knooppunten die de onderliggende elementen definiëren.

  • Als een Expand knooppunt niet is gespecificeerd in een visualisatievermelding, gebruiken de kinderen de standaarduitbreidingsregels.

  • Als een Expand knooppunt is opgegeven zonder onderliggende knooppunten, kan het type niet worden uitgebreid in de debugvensters.

Uibreiding van artikel

Het element Item is het meest eenvoudige en algemene element in een Expand-knooppunt. Item definieert een enkelvoudig kindelement. Een CRect-klasse met velden top, left, righten bottom heeft bijvoorbeeld de volgende visualisatievermelding:

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

In het venster foutopsporingsprogramma ziet het CRect type eruit als in dit voorbeeld:

CRect met itemelementuitbreiding

Het foutopsporingsprogramma evalueert de expressies die zijn opgegeven in de elementen Width en Height en toont de waarden in de kolom Waarde van het variabelevenster.

Het foutopsporingsprogramma maakt voor elke aangepaste expansie automatisch het knooppunt [Onbewerkte weergave] aan. In de voorgaande schermopname ziet u de [Onbewerkte weergave] knooppunt uitgevouwen om te laten zien hoe de standaard onbewerkte weergave van het object verschilt van de Natvis-visualisatie. De standaarduitbreiding maakt een subboom voor de basisklasse en vermeldt alle gegevensleden van de basisklasse als kinderen.

Notitie

Als de expressie van het itemelement verwijst naar een complex type, is het item knooppunt zelf uitbreidbaar.

Uitbreiding van ArrayItems

Gebruik het ArrayItems-knooppunt om het type te laten interpreteren als een matrix en de afzonderlijke elementen ervan weer te geven met het Visual Studio-foutopsporingsprogramma. De visualisatie voor std::vector is een goed voorbeeld:

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

Een std::vector toont de afzonderlijke elementen wanneer deze in het variabelevenster worden uitgevouwen:

std::vector met ArrayItems-uitbreiding

Het knooppunt ArrayItems moet het volgende hebben:

  • Een Size-expressie (die moet resulteren in een geheel getal) voor het foutopsporingsprogramma om de lengte van de matrix te begrijpen.
  • Een ValuePointer-expressie die verwijst naar het eerste element (dat een aanwijzer moet zijn van een elementtype dat niet void*is).

De standaardwaarde van de ondergrens van de matrix is 0. Als u de waarde wilt overschrijven, gebruikt u een LowerBound element. De .natvis bestanden die zijn verzonden met Visual Studio, hebben voorbeelden.

Notitie

U kunt de []-operator gebruiken, bijvoorbeeld vector[i], met een enkeledimensionale matrixvisualisatie die gebruikmaakt van ArrayItems, zelfs als het type zelf (bijvoorbeeld CATLArray) deze operator niet toestaat.

U kunt ook multidimensionale matrices opgeven. In dat geval heeft het foutopsporingsprogramma iets meer informatie nodig om onderliggende elementen correct weer te geven:

<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>
      <LowerBound>0</LowerBound>
    </ArrayItems>
  </Expand>
</Type>
  • Direction geeft aan of de matrix zich in volgorde van rij-primaire of kolom-primaire bevindt.
  • Rank geeft de rang van de matrix aan.
  • Het element Size accepteert de impliciete $i parameter, die wordt vervangen door de dimensieindex om de lengte van de matrix in die dimensie te vinden.
    • In het vorige voorbeeld moet de expressie _M_extent.M_base[0] de lengte van de 0e dimensie geven, _M_extent._M_base[1] de eerste, enzovoort.
  • De LowerBound geeft de ondergrens aan van elke dimensie van de matrix. Voor multidimensionale matrices kunt u een expressie opgeven die gebruikmaakt van de impliciete $i parameter. De parameter $i wordt vervangen door de dimensieindex om de ondergrens van de matrix in die dimensie te vinden.
    • In het vorige voorbeeld beginnen alle dimensies bij 0. Als u echter ($i == 1) ? 1000 : 100 als ondergrens hebt, begint de 0e dimensie bij 100 en begint de eerste dimensie bij 1000.
      • , zoals [100, 1000], [100, 1001], [100, 1002], ... [101, 1000], [101, 1001],...

Hier ziet u hoe een tweedimensionaal Concurrency::array-object eruitziet in het venster foutopsporingsprogramma:

tweedimensionale matrix met matrixitems-uitbreiding

IndexListItems-uitbreiding

U kunt ArrayItems uitbreiding alleen gebruiken als de matrixelementen aaneengesloten in het geheugen zijn ingedeeld. Het foutopsporingsprogramma gaat naar het volgende element door simpelweg de aanwijzer te verhogen. Als u de index naar het waardeknooppunt wilt bewerken, gebruikt u IndexListItems knooppunten. Hier volgt een visualisatie met een IndexListItems knooppunt:

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

Het enige verschil tussen ArrayItems en IndexListItems is de ValueNode, die de volledige expressie verwacht voor het ith-element met de impliciete parameter voor $i.

Notitie

U kunt de []-operator gebruiken, bijvoorbeeld vector[i], met een enkeledimensionale matrixvisualisatie die gebruikmaakt van IndexListItems, zelfs als het type zelf (bijvoorbeeld CATLArray) deze operator niet toestaat.

Uitbreiding van LinkedListItems

Als het gevisualiseerde type een gekoppelde lijst vertegenwoordigt, kan de debugger zijn kinderen weergeven met behulp van een LinkedListItems-knooppunt. De volgende visualisatie voor het type CAtlList maakt gebruik van 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>

Het element Size verwijst naar de lengte van de lijst. HeadPointer verwijst naar het eerste element, NextPointer verwijst naar het volgende element en ValueNode verwijst naar de waarde van het item.

Het foutopsporingsprogramma evalueert de NextPointer- en ValueNode-uitdrukkingen in de context van het LinkedListItems-knooppuntelement, niet het ouderlijsttype. In het voorgaande voorbeeld heeft CAtlList een CNode-klasse (in atlcoll.h) die een knooppunt van de gekoppelde lijst is. m_pNext en m_element zijn velden van die CNode klasse, niet van de klasse CAtlList.

ValueNode kan leeg blijven of this gebruiken om naar het LinkedListItems knooppunt zelf te verwijzen.

Uitbreiding van CustomListItems

Met de CustomListItems-uitbreiding kunt u aangepaste logica schrijven voor het doorlopen van een gegevensstructuur, zoals een hashtabel. Gebruik CustomListItems om gegevensstructuren te visualiseren die C++-expressies kunnen gebruiken voor alles wat u moet evalueren, maar niet helemaal in de vorm passen voor ArrayItems, IndexListItemsof LinkedListItems.

U kunt Exec gebruiken om code in een CustomListItems-uitbreiding uit te voeren met behulp van de variabelen en objecten die in de uitbreiding zijn gedefinieerd. U kunt logische operators, rekenkundige operatoren en toewijzingsoperatoren gebruiken met Exec. U kunt Exec niet gebruiken om functies te evalueren, met uitzondering van intrinsieke functies van foutopsporingsprogramma ondersteund door de C++-expressie-evaluator.

De volgende visualisatiefunctie voor CAtlMap is een uitstekend voorbeeld waarin CustomListItems geschikt is.

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

Als het gevisualiseerde type een boom vertegenwoordigt, kan de debugger de boomstructuur doorlopen en zijn kinderen weergeven met behulp van een TreeItems knooppunt. Hier volgt de visualisatie voor het std::map type met behulp van een TreeItems-knooppunt:

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

De syntaxis is vergelijkbaar met het knooppunt LinkedListItems. LeftPointer, RightPointeren ValueNode worden geëvalueerd in de context van de boomknooppuntklasse. ValueNode kan leeg blijven of this gebruiken om naar het TreeItems knooppunt zelf te verwijzen.

UitgebreidItem-uitbreiding

Het ExpandedItem-element genereert een samengestelde weergave door eigenschappen van basisklassen of gegevensleden weer te geven alsof ze kinderen zijn van het gevisualiseerde type. De debugger evalueert de opgegeven expressie, en voegt de child nodes van het resultaat toe aan de kindlijst van het gevisualiseerde type.

Het type slimme aanwijzer auto_ptr<vector<int>> wordt bijvoorbeeld meestal weergegeven als:

auto_ptr<vector<int>> standaarduitbreiding

Als u de waarden van de vector wilt zien, moet u twee niveaus doorlopen in het variabelevenster, en door het _Myptr-lid navigeren. Door een ExpandedItem element toe te voegen, kunt u de _Myptr variabele uit de hiërarchie elimineren en de vectorelementen rechtstreeks bekijken:

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

auto_ptr<vector<int>> ExpandedItem expansion

In het volgende voorbeeld ziet u hoe u eigenschappen van de basisklasse in een afgeleide klasse samenvoegt. Stel dat de CPanel klasse is afgeleid van CFrameworkElement. In plaats van de eigenschappen te herhalen die afkomstig zijn van de basisklasse CFrameworkElement, voegt de visualisatie van het ExpandedItem knooppunt deze eigenschappen toe aan de onderliggende lijst van de CPanel-klasse.

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

De opmaakaanduidingen en, waarmee visualisatiematching voor de afgeleide klasse moet worden uitgeschakeld, zijn hier noodzakelijk. Anders zou de uitdrukking *(CFrameworkElement*)this ervoor zorgen dat de CPanel-visualisatie opnieuw wordt toegepast, omdat de standaardregels voor visualisatietypetoewijzing deze als de meest geschikte beschouwen. Gebruik de en opmaakaanduiding om de debugger te instrueren om de basisklassevisualisatie te gebruiken, of de standaarduitbreiding te gebruiken wanneer de basisklasse geen visualisatie heeft.

uitbreiding van synthetische items

Hoewel het ExpandedItem element een platte weergave van gegevens biedt door hiërarchieën te elimineren, doet het Synthetic knooppunt het tegenovergestelde. Hiermee kunt u een kunstmatig kindelement maken dat geen resultaat is van een uitdrukking. Het kunstmatige element kan zelf kind elementen hebben. In het volgende voorbeeld gebruikt de visualisatie voor het type Concurrency::array een Synthetic-knooppunt om een diagnostisch bericht weer te geven aan de gebruiker:

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

gelijktijdigheid::Matrix met synthetische elementuitbreiding

Intrinsieke uitbreiding

Een aangepaste intrinsieke functie die kan worden aangeroepen vanuit een expressie. Een <Intrinsic> element moet worden vergezeld van een foutopsporingsprogrammaonderdeel dat de functie implementeert via de interface IDkmIntrinsicFunctionEvaluator140. Zie Implementeren van een aangepaste NatVis intrinsieke functievoor meer informatie over het implementeren van een aangepaste intrinsieke functie.

<Type Name="std::vector&lt;*&gt;">
  <Intrinsic Name="size" Expression="(size_t)(_Mypair._Myval2._Mylast - _Mypair._Myval2._Myfirst)" />
  <Intrinsic Name="capacity" Expression="(size_t)(_Mypair._Myval2._Myend - _Mypair._Myval2._Myfirst)" />
  <DisplayString>{{ size={size()} }}</DisplayString>
  <Expand>
    <Item Name="[capacity]" ExcludeView="simple">capacity()</Item>
    <Item Name="[allocator]" ExcludeView="simple">_Mypair</Item>
    <ArrayItems>
      <Size>size()</Size>
      <ValuePointer>_Mypair._Myval2._Myfirst</ValuePointer>
    </ArrayItems>
  </Expand>
</Type>

HResult-element

Met het element HResult kunt u de informatie aanpassen die wordt weergegeven voor een HRESULT- in foutopsporingsprogrammavensters. Het element HRValue moet de 32-bits waarde van de HRESULT- bevatten die moet worden aangepast. Het element HRDescription bevat de informatie die moet worden weergegeven in het venster foutopsporingsprogramma.


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

UIVisualizer-element

Een UIVisualizer-element registreert een plug-in voor grafische visualisaties bij het foutopsporingsprogramma. Een grafische visualisatie maakt een dialoogvenster of een andere interface die een variabele of object op een manier weergeeft die consistent is met het gegevenstype. De visualizer-invoegtoepassing moet worden gemaakt als een VSPackage-en moet een service beschikbaar maken die de debugger kan gebruiken. Het bestand .natvis bevat registratiegegevens voor de invoegtoepassing, zoals de naam, de GUID (Globally Unique Identifier) van de weergegeven service en de typen die kunnen worden gevisualiseerd.

Hier volgt een voorbeeld van een 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>
  • Een ServiceId - Id kenmerkpaar identificeert een UIVisualizer. De ServiceId is de GUID van de service die het visualizer-pakket beschikbaar maakt. Id is een unieke identificator waarmee visualisatiehulpmiddelen worden onderscheiden als een dienst meer dan één visualisatiehulpmiddel biedt. In het voorgaande voorbeeld biedt dezelfde visualizer-service twee visualizers.

  • Het kenmerk MenuName definieert een visualisatienaam die moet worden weergegeven in de vervolgkeuzelijst naast het vergrootglaspictogram in het foutopsporingsprogramma. Bijvoorbeeld:

    snelmenu UIVisualizer-menu

Elk type dat is gedefinieerd in het bestand .natvis, moet expliciet een lijst weergeven van ui-visualisaties die het kunnen weergeven. De debugger stemt de visualizerverwijzingen in de typevermeldingen af op de geregistreerde visualizers. De volgende typevermelding voor std::vector verwijst bijvoorbeeld naar de UIVisualizer in het voorgaande voorbeeld.

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

U ziet een voorbeeld van een UIVisualizer in de extensie Image Watch die wordt gebruikt om bitmaps in het geheugen weer te geven.

Het element CustomVisualizer

CustomVisualizer is een uitbreidbaar punt dat een VSIX-extensie aangeeft die u schrijft om visualisaties in Visual Studio Code te beheren. Zie de Visual Studio SDKvoor meer informatie over het schrijven van VSIX-extensies.

Het is veel meer werk om een aangepaste visualisatie te schrijven dan een XML Natvis-definitie, maar u bent vrij van beperkingen over wat Natvis doet of niet ondersteunt. Aangepaste visualizers hebben toegang tot de volledige set uitbreidbaarheids-API's van de debugger, die het gedebugde proces kunnen doorzoeken en wijzigen of kunnen communiceren met andere onderdelen van Visual Studio.

U kunt de kenmerken Condition, IncludeViewen ExcludeView voor CustomVisualizer elementen gebruiken.

Beperkingen

Natvis-aanpassingen werken met klassen en structs, maar niet met typedefs.

Natvis biedt geen ondersteuning voor visualisaties voor primitieve typen (bijvoorbeeld int, bool) of voor aanwijzers naar primitieve typen. In dit scenario kunt u de indelingsaanduiding gebruiken geschikt voor uw use-case. Als u bijvoorbeeld double* mydoublearray in uw code gebruikt, kunt u een matrixnotatieaanduiding gebruiken in het venster Watch van het foutopsporingsprogramma, zoals de expressie mydoublearray, [100], waarin de eerste 100 elementen worden weergegeven.