Visual Studio visualisation de débogage native (natvis) pour C++/WinRT

L’extension Visual Studio C++/WinRT (VSIX) vous offre une visualisation de débogage native dans Visual Studio (natvis) des types projetés C++/WinRT. Cela vous offre une expérience comparable au débogage en C#.

Note

Pour plus d’informations sur l’extension Visual Studio C++/WinRT (VSIX), consultez Prise en charge de C++/WinRT dans Visual Studio et le fichier VSIX.

Activation de natvis

Natvis est automatiquement activé pour une build de débogage, car WINRT_NATVIS est défini lorsque le symbole _DEBUG est défini.

Voici comment y adhérer pour une build de mise en production.

  • Compilez votre code avec le symbole WINRT_NATVIS défini. Cette opération exporte une fonction WINRT_abi_val, qui fournit au visualiseur de débogage un point d’entrée pour évaluer les valeurs des propriétés dans le processus cible.
  • Générez une base de données PDB complète. Cela est dû au fait que le visualiseur de débogage utilise l’évaluateur d’expression C++ Visual Studio, qui à son tour nécessite des définitions symboliques pour les types de propriétés affichés.
  • Un type visualisable doit signaler une classe runtime ou une interface définie dans des métadonnées détectables. Il effectue cette opération via son implémentation d’IInspectable ::GetRuntimeClassName.

Compte tenu de ce qui précède, le visualiseur de débogage fonctionne de manière optimale avec les types système Windows dont les métadonnées se trouvent dans le dossier C:\Windows\System32\WinMetadata. Toutefois, il peut également prendre en charge les types définis par l’utilisateur et le débogage à distance, à condition que vous localisiez correctement les .winmd fichiers.

Utilisation de métadonnées personnalisées

Le visualiseur de débogage recherche les métadonnées définies par l’utilisateur (.winmd fichiers) en même temps que le processus .exe. Il utilise un algorithme similaire à celui de RoGetMetaDataFile, en recherchant les sous-chaînes successives du nom de type complet. Par exemple, si le type en cours de visualisation est Contoso.Controls.Widget, le visualiseur recherche, en séquence, pour :

  • Contoso.Controls.Widget.winmd
  • Contoso.Controls.winmd
  • Contoso.winmd

Débogage à distance avec des métadonnées personnalisées

Lors du débogage à distance, le processus .exe n’est pas exécuté localement, de sorte que la recherche de métadonnées personnalisées (mentionnée dans la section précédente) échoue. Dans ce cas, le visualiseur revient à un dossier de cache local (%TEMP%) pour un fichier approprié .winmd . S’il en trouve un, il enregistre la taille et la date du fichier, puis recherche la cible de débogage distante pour la même .winmd chose en même temps que le fichier binaire. Si nécessaire, le fichier distant est téléchargé, mettant à jour le cache local. Cette stratégie garantit que le .winmd mis en cache localement est toujours à jour, tout en fournissant un moyen de mettre manuellement en cache un . winmd s’il est introuvable à distance (par exemple, si le déploiement F5 ne l’a pas placé).

Pour obtenir un exemple de comportement de mise en cache, consultez la section Résolution des problèmes ci-dessous.

Troubleshooting

Le visualiseur de débogage utilise l’évaluateur d’expressions C++ de Visual Studio pour appeler la fonction exportée WINRT_abi_val afin d’obtenir les valeurs des propriétés. Normalement, le visualiseur peut intercepter les exceptions non gérées et continuer à fonctionner en mode dégradé, en affichant «<Objet non initialisé ou informations non disponibles>» dans les fenêtres Espion de Visual Studio.

Cela est utile lorsque le visualiseur tente d’évaluer une variable locale en dehors de son étendue de durée de vie (par exemple, avant la construction). Dans certains contextes, tels que les tests unitaires, un filtre d’exception non géré est installé. Cela peut entraîner l’arrêt du processus lorsque l’évaluateur d’expressions C++ rencontre une défaillance. Pour éviter les pannes, le visualiseur effectue plusieurs appels VirtualQuery dans WINRT_abi_val.

Diagnostics

Si une propriété ne s’affiche pas correctement, activez les messages de diagnostic Natvis détaillés dans Visual Studio (Outils>Options>Débogage>Fenêtre de sortie>Messages de diagnostic Natvis), puis observez la fenêtre Sortie afin d’y repérer les erreurs Natvis.

L’extrait suivant montre plusieurs tentatives de détection d’un fichier .winmd, suivies d’un téléchargement depuis la cible distante vers le dossier de cache local, puis du chargement de ce fichier .winmd.

Natvis C++/WinRT: Looking for C:\Users\...\AppData\Local\DevelopmentFiles\ffcddd4f-cfc0-44cb-b736-0b2d026def77VS.Debug_x64....\Consoso.Controls.Widget.winmd
Natvis C++/WinRT: Looking for C:\Users\...\AppData\Local\DevelopmentFiles\ffcddd4f-cfc0-44cb-b736-0b2d026def77VS.Debug_x64....\Consoso.Controls.winmd
Natvis C++/WinRT: Downloading C:\Users\...\AppData\Local\DevelopmentFiles\ffcddd4f-cfc0-44cb-b736-0b2d026def77VS.Debug_x64....\Consoso.Controls.winmd
Natvis C++/WinRT: Loaded C:\Users\...\AppData\Local\Temp\Consoso.Controls.winmd

Si le visualiseur ne parvient pas à trouver un .winmd fichier, cette erreur est générée :

Natvis C++/WinRT: Could not find metadata for Consoso.Controls.Widget

Il existe plusieurs autres scénarios d’erreur qui produisent tous des diagnostics.

Si les métadonnées sont disponibles, alors les diagnostics en sortie afficheront de nombreux appels de ce type :

Natvis C++/WinRT: WINRT_abi_val(*(::IUnknown**)0x32dd4ffc18, L"{96369F54-8EB6-48F0-ABCE-C1B211E627C3}", 0).s,sh
Natvis C++/WinRT: WINRT_abi_val(*(::IUnknown**)0x32dd4ffc18, L"{AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90}", -2).s,sh

Le premier est un appel à IStringable.ToString pour obtenir la représentation sous forme de chaîne de caractères d’un type complexe (la valeur d’affichage non développée).

Le deuxième est un appel à IInspectable ::GetRuntimeClassName, afin de réfléchir aux propriétés du type.

Les appels de WINRT_abi_val suivants sont des évaluations de propriétés pour chaque interface découverte sur le type.

Invocation de WINRT_abi_val

Vous pouvez utiliser les fenêtres Immediate/Command de Visual Studio pour appeler directement WINRT_abi_val pour le dépannage.

Par exemple, en fonction d’une variable projetée pouvant être chaîne, vous pouvez évaluer son IStringable.ToString comme suit :

>? WINRT_abi_val((::IUnknown*)&stringable, L"{96369F54-8EB6-48F0-ABCE-C1B211E627C3}", 0).s,sh
L"string"