C++/WinRT 用 Visual Studio ネイティブ デバッグ視覚化 (natvis)
C++/WinRT Visual Studio 拡張機能 (VSIX) は、C++/WinRT の投影された型の Visual Studio ネイティブのデバッグの視覚化 (natvis) を提供します。 これにより、C# デバッグと同様のエクスペリエンスが実現します。
注意
C++/WinRT Visual Studio Extension (VSIX) についての詳細は、「C++/WinRT の Visual Studio サポートと VSIX」を参照してください。
Natvis の有効化
_DEBUG シンボルが定義されているときには WINRT_NATVIS が定義されているため、デバッグ ビルドの場合、Natvis は自動的にオンになります。
次にリリース ビルドに対してこれを選択する方法を示します。
- シンボル WINRT_NATVIS 定義されたコードをコンパイルします。 これにより、WINRT_abi_val 関数がエクスポートされることで、デバッグ ビジュアライザーがターゲットプロセスのプロパティ値を評価するためのエントリ ポイントが提供されます。
- 完全な PDB を生成します。 これは、デバッグ ビジュアライザーが Visual Studio C++ の式エバリュエーターを使用し、そのために、表示されるプロパティの型にシンボリック定義が必要になるためです。
- 視覚化された型は、検出可能なメタデータで定義されているランタイム クラスまたはインターフェイスを報告する必要があります。 これは、IInspectable::GetRuntimeClassName の実装によって行われます。
上記の場合、デバッグ ビジュアライザーは、C:\Windows\System32\WinMetadata
フォルダーでメタデータを見つけることができるような Windows システムで最適に機能します。 ただし、.winmd
ファイルを適切に見つけることができる場合は、ユーザー定義型とリモート デバッグもサポートできます。
カスタム メタデータの使用
デバッグ ビジュアライザーでは、プロセスの .exe
と共にユーザー定義のメタデータ (.winmd
ファイル) が検索さ ます。 RoGetMetaDataFile のようなアルゴリズムを使用して、完全修飾された型名の連続する部分文字列を調査します。 たとえば、視覚化される型が Contoso.Controls.Widget の場合、ビジュアライザーは次のものを順番に探します。
- Contoso.Controls.Widget.winmd
- Contoso.Controls.winmd
- Contoso.winmd
カスタム メタデータを使用したリモート デバッグ
リモートデバッグの場合、プロセスの .exe
はローカルではないため、(前のセクションで説明した) カスタム メタデータの検索は失敗します。 この場合、ビジュアライザーは、適切な .winmd
ファイルのローカル キャッシュ フォルダー (%TEMP%
) にフォール バックし ます。 見つかった場合は、ファイルのサイズと日付を記録し、次に、同じ .winmd
のリモート デバッグ ターゲットをバイナリと共に検索します。 必要に応じて、リモート ファイルがダウンロードされ、ローカル キャッシュが更新されます。 この戦略により、ローカルにキャッシュされた .winmd
が常に最新の状態になり、手動でキャッシュする手段も提供されます。リモートで見つからない場合 (たとえば、F5 による展開でそこに配置されなかった場合) に winmd
を手動でキャッシュする手段が提供されます。
キャッシュ動作の例については、後述の「トラブルシューティング」セクションを参照してください。
トラブルシューティング
デバッグ ビジュアライザーは、Visual Studio C++ 式エバリュエーターを使用して、エクスポートされた WINRT_abi_val 関数を呼び出してプロパティ値を取得します。 通常、ビジュアライザーは未処理の例外をキャッチして適切にレベルを低下させ、Visual Studio の [ウォッチ] ウィンドウに "<Object uninitialized or information unavailable>" (オブジェクトが初期化されていないか、情報が利用できません) を表示します。
これは、ビジュアライザーが有効期間の範囲外 (構築前など) にローカル変数を評価しようとしたときに便利です。 単体テストなどの一部のコンテキストでは、ハンドルされない例外フィルターがインストールされます。 これにより、C++ 式エバリュエーターで障害が発生したときにプロセスが終了することがあります。 障害を回避するために、ビジュアライザーは、WINRT_abi_val でいくつかの VirtualQuery の呼び出しを行います。
診断
プロパティが正しく表示されていない場合は、Visual Studio で詳細な Natvis 診断をオンにし ([ツール]>[オプション]>[デバッグ]>[出力ウィンドウ]>[Natvis 診断メッセージ])、[出力] ウィンドウで Natvis エラーを確認します。
次の抜粋では、.winmd
ファイルをプローブした後に、リモート ターゲットからローカル キャッシュ フォルダーにダウンロードし、さらにその .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
ビジュアライザーが .winmd
ファイルを見つけられなかった場合、次のエラーが生成されます。
Natvis C++/WinRT: Could not find metadata for Consoso.Controls.Widget
他にもいくつかのエラー シナリオがあり、そのすべてで診断が生成されます。
メタデータを使用できる場合、出力診断では次のような多くの呼び出しが表示されます。
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
1 つ目は、複合型の文字列形式 (展開されていない表示値) を取得するための IStringable.ToString の呼び出しです。
2 つ目は、型のプロパティに反映させるための IInspectable::GetRuntimeClassNameの呼び出しです。
後続の WINRT_abi_val の呼び出しは、型で検出された各インターフェイスのプロパティの評価です。
WINRT_abi_val の呼び出し
Visual Studio の [イミディエイト]/[コマンド] ウィンドウを使用すると、トラブルシューティングのために WINRT_abi_val を直接呼び出すことができます。
たとえば、想定される変数 stringable が指定されると、その IStringable.ToString を次のように評価できます。
>? WINRT_abi_val((::IUnknown*)&stringable, L"{96369F54-8EB6-48F0-ABCE-C1B211E627C3}", 0).s,sh
L"string"