Встроенная визуализация отладки natvis в Visual Studio для C++/WinRT

Расширение C++/WinRT Visual Studio (VSIX) предоставляет Visual Studio собственную визуализацию отладки (natvis) проектируемых типов C++/WinRT. Это обеспечивает возможности, аналогичные отладке в C#.

Note

Дополнительные сведения о расширении Visual Studio для C++/WinRT (VSIX) см. в статье Поддержка C++/WinRT в Visual Studio и VSIX.

Включение natvis

Natvis автоматически включен для отладочной сборки, так как WINRT_NATVIS определяется при определении символа _DEBUG .

Вот как включить это для релизной сборки.

  • Скомпилируйте код с заданным символом WINRT_NATVIS. Это экспортирует функцию WINRT_abi_val , которая предоставляет точку входа для визуализатора отладки для оценки значений свойств в целевом процессе.
  • Создайте полную PDB. Это связано с тем, что визуализатор отладки использует средство оценки выражений C++ Visual Studio, которое, в свою очередь, требует символьных определений для отображаемых типов свойств.
  • Визуализированный тип должен сообщать класс среды выполнения или интерфейс, определенный в обнаруженных метаданных. Это происходит через реализацию IInspectable::GetRuntimeClassName.

Учитывая выше, визуализатор отладки лучше всего работает с Windows системными типами, для которых метаданные можно найти в папкеC:\Windows\System32\WinMetadata. Однако он также может поддерживать определяемые пользователем типы и удаленную отладку, при условии правильного поиска .winmd файлов.

Использование пользовательских метаданных

Визуализатор отладки ищет пользовательские метаданные (.winmd файлы) вместе с процессом .exe. Он использует алгоритм, аналогичный алгоритму, используемому в RoGetMetaDataFile, последовательно проверяя подстроки полностью квалифицированного имени типа. Например, если визуализируемый тип — Contoso.Controls.Widget, то визуализатор ищет в следующем порядке:

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

Удаленная отладка с пользовательскими метаданными

При удаленной отладке процесс .exe не является локальным, поэтому поиск пользовательских метаданных (упомянутых в предыдущем разделе) завершается ошибкой. В этом случае визуализатор возвращается в папку локального кэша (%TEMP%) для подходящего .winmd файла. Если он находит его, он записывает размер и дату файла, а затем выполняет поиск целевого объекта удаленной отладки наряду .winmd с двоичным файлом. При необходимости удалённый файл загружается, обновляя локальный кэш. Эта стратегия гарантирует, что локально кэшированные .winmd данные всегда актуальны, а также предоставляют средства для кэширования вручную. winmd если его не удаётся найти удалённо (например, если развёртывание через F5 не поместило его туда).

Пример поведения кэширования см. в разделе "Устранение неполадок " ниже.

Troubleshooting

Визуализатор отладки использует средство оценки выражений C++ Visual Studio для вызова экспортируемой функции WINRT_abi_val для получения значений свойств. Как правило, визуализатор может перехватывать необработанные исключения и корректно обрабатывать такие ситуации, отображая "<Объект не инициализирован или информация недоступна>" в окнах Контроль Visual Studio.

Это полезно, когда визуализатор пытается вычислить значение локальной переменной вне времени её жизни (например, до создания). В некоторых контекстах, например при модульном тестировании, устанавливается фильтр необработанных исключений. Это может привести к завершению процесса при сбоях вычислителя выражений C++. Чтобы предотвратить сбой, визуализатор выполняет несколько вызовов VirtualQuery в WINRT_abi_val.

Диагностика

Если свойство отображается неправильно, включите подробную диагностику Natvis в Visual Studio (Сервис>Параметры>Отладка>Окно вывода>Диагностические сообщения 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.ToStringing для получения строкового представления сложного типа (необъясненное отображаемое значение).

Второй — вызов IInspectable::GetRuntimeClassName, чтобы отразить свойства типа.

Последующие вызовы WINRT_abi_val — это оценки свойств для каждого интерфейса, обнаруженного в типе.

Вызов WINRT_abi_val

Для диагностики можно использовать окна Visual Studio Immediate/Command, чтобы напрямую вызвать WINRT_abi_val.

Например, для проецируемой переменной stringable можно вычислить результат IStringable.ToString следующим образом:

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