Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
La extensión de Visual Studio para C++/WinRT (VSIX) le ofrece visualización de depuración nativa de Visual Studio (natvis) para los tipos proyectados de C++/WinRT. Esto le ofrece una experiencia similar a la de la depuración en C#.
Note
Para obtener más información sobre la extensión de Visual Studio (VSIX) de C++/WinRT, consulta Visual Studio compatibilidad con C++/WinRT y VSIX.
Habilitar natvis
Natvis está habilitado automáticamente en una compilación de depuración porque WINRT_NATVIS se define cuando se define el símbolo _DEBUG.
A continuación se explica cómo activarlo para una compilación de lanzamiento.
- Compile el código con el símbolo WINRT_NATVIS definido. Al hacerlo, exporta una función WINRT_abi_val, que proporciona el punto de entrada para que el visualizador de depuración evalúe los valores de las propiedades en el proceso de destino.
- Genere una base de datos PDB completa. Esto se debe a que el visualizador de depuración usa el Visual Studio evaluador de expresiones de C++, que a su vez requiere definiciones simbólicas para los tipos de propiedad mostrados.
- Un tipo visualizado debe indicar una clase en tiempo de ejecución o una interfaz definida en metadatos detectables. Lo hace a través de su implementación de IInspectable::GetRuntimeClassName.
Dado lo anterior, el visualizador de depuración funciona mejor con los tipos de sistema de Windows para los que se pueden encontrar metadatos en la carpeta C:\Windows\System32\WinMetadata. Sin embargo, también puede ser compatible con tipos definidos por el usuario y la depuración remota, siempre que localice correctamente los archivos .winmd.
Uso de metadatos personalizados
El visualizador de depuración busca metadatos definidos por el usuario (.winmd archivos) junto con el proceso .exe. Utiliza un algoritmo similar al de RoGetMetaDataFile, sondeando subcadenas sucesivas del nombre de tipo completo y cualificado. Por ejemplo, si el tipo visualizado es Contoso.Controls.Widget, el visualizador busca, en este orden:
- Contoso.Controls.Widget.winmd
- Contoso.Controls.winmd
- Contoso.winmd
Depuración remota con metadatos personalizados
Al depurar remotamente, el proceso .exe no es local, por lo que se produce un error en la búsqueda de metadatos personalizados (mencionados en la sección anterior). En ese caso, el visualizador vuelve a una carpeta de caché local (%TEMP%) para un archivo adecuado .winmd . Si encuentra una, registra el tamaño y la fecha del archivo y, a continuación, busca en el destino de depuración remota el mismo .winmd junto con el binario. Si es necesario, se descarga el archivo remoto, actualizando la caché local. Esta estrategia garantiza que el almacenamiento .winmd en caché local esté siempre actualizado, así como proporcionar un medio para almacenar en caché manualmente un .
winmd si no se puede encontrar en remoto (por ejemplo, si el despliegue de F5 no lo colocó allí).
Para obtener un ejemplo del comportamiento de almacenamiento en caché, consulte la sección Solución de problemas siguiente.
Troubleshooting
El visualizador de depuración usa el evaluador de expresiones de C++ Visual Studio para invocar la función exportada WINRT_abi_val para obtener valores de propiedad. Normalmente, el visualizador puede detectar excepciones no controladas y degradarse de forma controlada, mostrando "<Objeto no inicializado o información no disponible>" en las ventanas Inspección de Visual Studio.
Esto resulta útil cuando el visualizador intenta evaluar una variable local fuera de su ámbito de duración (por ejemplo, antes de la construcción). En algunos contextos, como las pruebas unitarias, se instala un filtro de excepción no controlado. Esto puede hacer que el proceso finalice cuando se produzcan errores del evaluador de expresiones de C++. Para evitar errores, el visualizador realiza varias llamadas a VirtualQuery en WINRT_abi_val.
Diagnostics
Si una propiedad no se muestra correctamente, active el diagnóstico detallado de Natvis en Visual Studio (Herramientas>Opciones>Depuración>Ventana de salida>Mensajes de diagnóstico de Natvis) y, a continuación, revise la ventana Salida para comprobar si hay errores de Natvis.
En el fragmento siguiente se muestran varios intentos de sondear un .winmd archivo, seguido de una descarga desde el destino remoto a la carpeta de caché local y, a continuación, una carga de ese .winmd archivo.
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
Si el visualizador no encuentra un .winmd archivo, se genera este error:
Natvis C++/WinRT: Could not find metadata for Consoso.Controls.Widget
Hay una serie de otros escenarios de error que generan diagnósticos.
Si los metadatos están disponibles, los diagnósticos de salida mostrarán muchas llamadas como esta:
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
La primera es una llamada a IStringable.ToString para obtener la representación en forma de cadena de un tipo complejo (el valor de visualización sin expandir).
El segundo es una llamada a IInspectable::GetRuntimeClassName, para reflejar las propiedades del tipo.
Las llamadas WINRT_abi_val posteriores son evaluaciones de propiedades para cada interfaz detectada en el tipo .
Invocar WINRT_abi_val
Puede usar las ventanas Visual Studio Comando inmediato/ para invocar directamente WINRT_abi_val para solucionar problemas.
Por ejemplo, dada una variable proyectada stringable, puede evaluar su IStringable.ToString como:
>? WINRT_abi_val((::IUnknown*)&stringable, L"{96369F54-8EB6-48F0-ABCE-C1B211E627C3}", 0).s,sh
L"string"