適用於 C++/WinRT 的 Visual Studio 原生偵錯視覺效果 (natvis)

C++/WinRT Visual Studio 延伸模組 (VSIX) 提供您 C++/WinRT 投影類型的 Visual Studio 原生偵錯視覺效果 (natvis)。 這提供類似 C# 偵錯的體驗。

注意

如需 C++/WinRT Visual Studio 延伸模組 (VSIX) 的詳細資訊,請參閱C++/WinRT 的 Visual Studio 支援,以及 VSIX

啟用 natvis

Natvis 會自動開啟偵錯組建,因為定義 _DEBUG 符號時會定義 WINRT_NATVIS

以下是如何針對發行組建加入。

  • 使用定義的符號 WINRT_NATVIS 編譯程式碼。 這樣做會匯出 WINRT_abi_val 函式,此函式會提供偵錯視覺特效播放器的進入點,以評估目標程序中的屬性值。
  • 產生完整的 PDB。 這是因為偵錯視覺特效播放器會使用 Visual Studio C++ 運算式評估工具,這反過來需要顯示屬性類型的符號定義。
  • 視覺化類型必須報告執行階段類別或在可探索中繼資料中定義的介面。 它會透過實作 IInspectable::GetRuntimeClassName 來執行此作業。

鑑於上述情況,偵錯視覺特效播放器最適合用於可在 C:\Windows\System32\WinMetadata 資料夾中找到中繼資料的 Windows 系統類型。 不過,也可以支援使用者定義的類型和遠端偵錯,前提是您正確地找到 .winmd 檔案。

使用自訂中繼資料

偵錯視覺特效播放器會尋找使用者定義中繼資料 (.winmd 檔案) 以及程序 .exe。 其會使用類似於 RoGetMetaDataFile 的演算法,探查完整類型名稱的後續子字串。 例如,如果視覺化的類型是 Contoso.Controls.Widget,則視覺特效播放器會依序查看:

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

使用自訂中繼資料進行遠端偵錯

遠端偵錯時,程序 .exe 不是本機,因此搜尋自訂中繼資料 (上一節所述) 會失敗。 在此情況下,視覺特效播放器會回到適合的 .winmd 檔案的本機快取資料夾 (%TEMP%)。 如果找到檔案,則會記錄檔案的大小和日期,然後針對相同 .winmd 以及二進位檔搜尋遠端偵錯目標。 如有必要,會下載遠端檔案,並更新本機快取。 此策略可確保本機快取的 .winmd 一律為最新狀態,並提供手動快取的方法。winmd 如果無法從遠端找到 (例如,如果 F5 部署未放置於該處)。

如需快取行為的範例,請參閱下方疑難排解一節。

疑難排解

偵錯視覺特效播放器會使用 Visual Studio C++ 運算式評估工具叫用匯出的 WINRT_abi_val 函式,以取得屬性值。 一般而言,視覺特效播放器可以攔截未處理的例外狀況,並正常降級,在 Visual StudioWatch視窗中顯示 「<物件未初始化或資訊無法使用>」。

當視覺特效播放器嘗試在其存留期範圍之外評估區域變數時,這非常有用 (例如,在建構之前)。 在部分情況下 (例如單元測試) 已安裝未處理的例外狀況篩選器。 這可能會導致程序在 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

第一個是呼叫 IStringable.ToString,以取得複雜類型的字串表示法 (未展開的顯示值)。

第二個是呼叫 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"