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

C++/WinRT Visual Studio Extension (VSIX) memberikan visualisasi debug native Visual Studio (natvis) untuk jenis terproyeksi C++/WinRT. Ini memberi Anda pengalaman yang serupa dengan penelusuran kesalahan di C#.

Note

Untuk informasi selengkapnya tentang Ekstensi Visual Studio C++/WinRT (VSIX), lihat dukungan Visual Studio untuk C++/WinRT, dan VSIX.

Mengaktifkan natvis

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

Berikut cara mengaktifkannya untuk build rilis.

  • Kompilasikan kode Anda dengan simbol WINRT_NATVIS yang didefinisikan. Dengan demikian mengekspor fungsi WINRT_abi_val, yang menyediakan titik masuk bagi debug visualizer untuk mengevaluasi nilai properti di proses target.
  • Buat PDB lengkap. Ini karena visualizer debug menggunakan Visual Studio C++ Expression Evaluator, yang pada gilirannya memerlukan definisi simbolis untuk jenis properti yang ditampilkan.
  • Jenis 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, debug visualizer berfungsi paling baik dengan tipe sistem Windows yang metadatanya dapat ditemukan di folder C:\Windows\System32\WinMetadata. Namun, fitur ini juga dapat mendukung tipe yang ditentukan pengguna dan debugging jarak jauh, asalkan Anda menempatkan file .winmd dengan benar.

Menggunakan metadata kustom

Visualizer debug mencari metadata yang ditentukan pengguna (file .winmd) di samping proses .exe. Fungsi ini menggunakan algoritma yang mirip dengan RoGetMetaDataFile, dengan menelusuri substring berturut-turut dari nama tipe yang sepenuhnya memenuhi kualifikasi. Misalnya, jika tipe yang divisualisasikan adalah Contoso.Controls.Widget, maka visualizer akan mencari, secara berurutan, hal berikut:

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

Debug jarak jauh dengan metadata khusus

Saat melakukan proses debug jarak jauh, proses .exe tidak berada di komputer lokal, sehingga pencarian metadata kustom (yang disebutkan di bagian sebelumnya) gagal. Dalam hal itu, visualizer akan menggunakan folder cache lokal (%TEMP%) sebagai cadangan untuk file .winmd yang sesuai. Jika menemukannya, sistem akan mencatat ukuran dan tanggal file tersebut, lalu mencari .winmd yang sama di target debug jarak jauh, di samping binernya. Jika perlu, file jarak jauh diunduh, memperbarui cache lokal. Strategi ini memastikan bahwa cache .winmd lokal selalu diperbarui, serta menyediakan sarana untuk menyimpan cache secara manual . winmd jika tidak dapat ditemukan dari jarak jauh (misalnya, jika penyebaran F5 tidak meletakkannya di sana).

Untuk contoh cara kerja cache, lihat bagian Pemecahan Masalah di bawah ini.

Troubleshooting

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 tertangani, dan menurun dengan baik, menampilkan "<Objek yang tidak diinisialisasi 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). Dalam beberapa konteks, seperti pengujian unit, filter pengecualian yang tidak tertangani diinstal. Ini dapat menyebabkan proses terhenti ketika evaluator ekspresi C++ mengalami kesalahan. Untuk mencegah kesalahan, visualizer melakukan beberapa panggilan VirtualQuery dalam WINRT_abi_val.

Diagnostics

Jika properti tidak ditampilkan dengan benar, aktifkan diagnostik Natvis verbose di Visual Studio (Alat>Opsi>Men-debug>Jendela Output>Pesan diagnostik Natvis), lalu periksa jendela Output untuk melihat kesalahan Natvis.

Cuplikan berikut menunjukkan beberapa upaya untuk mencari file .winmd, diikuti dengan pengunduhan dari target jarak jauh ke folder cache lokal, dan kemudian memuat file .winmd tersebut.

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 lainnya 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 pemanggilan ke IStringable.ToString untuk mendapatkan representasi string dari tipe kompleks (nilai tampilan yang belum diperluas).

Yang kedua adalah pemanggilan ke IInspectable::GetRuntimeClassName untuk melakukan refleksi terhadap properti tipe tersebut.

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

Memanggil WINRT_abi_val

Anda dapat menggunakan jendela Immediate/Command di Visual Studio untuk secara langsung memanggil WINRT_abi_val guna pemecahan masalah.

Misalnya, untuk variabel terproyeksi stringable, Anda dapat mengevaluasi IStringable.ToString-nya sebagai:

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