Visual Studio visualisasi debug asli (natvis) untuk C++/WinRT

Ekstensi Visual Studio C++/WinRT (VSIX) memberi Anda Visual Studio visualisasi debug asli (natvis) dari jenis yang diproyeksikan C++/WinRT. Ini memberi Anda pengalaman yang mirip dengan debugging C #.

Catatan

Untuk info lebih lanjut tentang C ++/WinRT Visual Studio Extension (VSIX), lihat Visual Studio dukungan untuk C++/WinRT, dan VSIX.

Mengaktifkan natvis

Natvis secara otomatis menyala untuk build debug karena WINRT_NATVIS ditentukan saat simbol _DEBUG didefinisikan.

Berikut adalah cara untuk memilih ke dalamnya untuk membangun rilis.

  • Kompilasi kode Anda dengan simbol WINRT_NATVIS ditentukan. Melakukan hal itu mengekspor fungsi WINRT_abi_val , yang menyediakan titik masuk bagi visualizer debug untuk mengevaluasi nilai properti dalam proses target.
  • Hasilkan PDB penuh. Ini karena visualizer debug menggunakan Visual Studio C ++ Expression Evaluator, yang pada gilirannya memerlukan definisi simbolis untuk jenis properti yang ditampilkan.
  • Tipe yang divisualisasikan harus melaporkan kelas runtime atau antarmuka yang ditentukan dalam metadata yang dapat ditemukan. Ini dilakukan melalui implementasi IInspectable::GetRuntimeClassName.

Mengingat hal di atas, visualizer debug bekerja paling baik dengan jenis sistem Windows yang metadatanya dapat ditemukan di C:\Windows\System32\WinMetadata folder. Namun, ini juga dapat mendukung jenis yang ditentukan pengguna dan debugging jarak jauh, asalkan Anda menemukan .winmd file dengan benar.

Menggunakan metadata kustom

Visualizer debug mencari metadata (.winmd file) yang ditentukan pengguna di samping proses .exe. Ini menggunakan algoritma yang mirip dengan RoGetMetaDataFile, menyelidiki substring berturut-turut dari nama tipe yang sepenuhnya memenuhi syarat. Misalnya, jika jenis yang divisualisasikan adalah Contoso.Controls.Widget, maka visualizer terlihat, secara berurutan, untuk:

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

Debugging jarak jauh dengan metadata kustom

Saat debugging jarak jauh, prosesnya .exe tidak lokal, sehingga pencarian metadata kustom (disebutkan di bagian sebelumnya) gagal. Dalam hal ini, visualizer jatuh kembali ke folder cache lokal (%TEMP%) untuk file yang sesuai .winmd . Jika menemukannya, maka ia mencatat ukuran dan tanggal file, dan kemudian mencari target debugging jarak jauh untuk hal yang sama .winmd di samping biner. Jika perlu, file jarak jauh diunduh, memperbarui cache lokal. Strategi ini memastikan bahwa cache .winmd lokal selalu up to date, serta menyediakan sarana untuk caching manual.winmd jika tidak dapat ditemukan dari jarak jauh (misalnya, jika penyebaran F5 tidak meletakkannya di sana).

Untuk contoh perilaku caching, lihat bagian Pemecahan Masalah di bawah ini.

Pemecahan Masalah

Visualizer debug menggunakan Visual Studio C++ Expression Evaluator untuk memanggil fungsi WINRT_abi_val yang diekspor untuk mendapatkan nilai properti. Biasanya, visualizer dapat menangkap pengecualian yang tidak ditangani, dan menurunkan dengan anggun, menampilkan "<Objek yang tidak tahu atau informasi tidak tersedia>" di jendela Visual Studio Watch.

Itu berguna ketika visualizer mencoba mengevaluasi variabel lokal di luar cakupan masa pakainya (misalnya, sebelum konstruksi). H Dalam beberapa konteks, seperti tes unit, filter pengecualian yang tidak ditangani diinstal. Hal ini dapat menyebabkan proses berakhir ketika evaluator ekspresi C ++ salah. Untuk mencegah kesalahan, visualizer membuat beberapa panggilan VirtualQuery di WINRT_abi_val.

Diagnostik

Jika properti tidak ditampilkan dengan benar, aktifkan diagnostik natvis verbose di Visual Studio (pesan diagnostikToolsOptionsDebuggingOutput>>>WindowNatvis>), lalu amati jendela Output untuk kesalahan natvis.

Kutipan berikut menunjukkan beberapa upaya untuk .winmd menyelidiki file, diikuti dengan unduhan dari target jarak jauh ke folder cache lokal, dan kemudian memuat file itu .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

Jika visualizer gagal menemukan .winmd file, maka kesalahan ini dihasilkan:

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

Ada sejumlah skenario kesalahan lain yang semuanya menghasilkan diagnostik.

Jika metadata tersedia, maka diagnostik output akan menampilkan banyak panggilan seperti ini:

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

Yang pertama adalah panggilan ke IStringable.ToString untuk mendapatkan representasi string dari tipe kompleks (nilai tampilan yang tidak diekspansi).

Yang kedua adalah panggilan ke IInspectable::GetRuntimeClassName, untuk merefleksikan properti tipe.

Panggilan WINRT_abi_val berikutnya adalah evaluasi properti untuk setiap antarmuka yang ditemukan pada jenis tersebut.

Memohon WINRT_abi_val

Anda dapat menggunakan jendela Visual StudioImmediateCommand/ untuk langsung memanggil WINRT_abi_val untuk pemecahan masalah.

Misalnya, mengingat variabel yang diproyeksikan dapat di stringable, Anda dapat mengevaluasi IStringable.ToString-nya sebagai:

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