Natvis (visualização de depuração nativa) do Visual Studio para C++/WinRT

O VSIX (Extensão do Visual Studio) para C++/WinRT fornece o Natvis (visualização de depuração nativa) do Visual Studio de tipos projetados do C++/WinRT. Isso fornece uma experiência semelhante à depuração do C#.

Note

Para obter mais informações sobre a VSIX (Extensão de Visual Studio do C++/WinRT), consulte Visual Studio suporte para C++/WinRT e o VSIX.

Habilitar natvis

O Natvis é ativado automaticamente em uma compilação de depuração porque WINRT_NATVIS é definido quando o símbolo _DEBUG é definido.

Veja como aceitar isso para um build de versão.

  • Compile seu código com o símbolo WINRT_NATVIS definido. Ao fazer isso, exporta uma função WINRT_abi_val, que fornece o ponto de entrada para o visualizador de depuração avaliar os valores das propriedades no processo de destino.
  • Gere um PDB completo. Isso ocorre porque o visualizador de depuração usa o avaliador de expressão Visual Studio C++, que, por sua vez, requer definições simbólicas para tipos de propriedade exibidos.
  • Um tipo visualizado deve relatar uma classe de runtime ou uma interface definida em metadados detectáveis. Ele faz isso por meio de sua implementação de IInspectable::GetRuntimeClassName.

Diante do exposto, o visualizador de depuração funciona melhor com tipos de sistema do Windows cujos metadados podem ser encontrados na pasta C:\Windows\System32\WinMetadata. No entanto, ele também pode oferecer suporte a tipos definidos pelo usuário e à depuração remota, desde que você localize corretamente os arquivos .winmd.

Usando metadados personalizados

O visualizador de depuração procura metadados definidos pelo usuário (arquivos .winmd) ao lado do processo .exe. Ele usa um algoritmo semelhante ao do RoGetMetaDataFile, investigando subcadeias de caracteres sucessivas do nome do tipo totalmente qualificado. Por exemplo, se o tipo que está sendo visualizado é Contoso.Controls.Widget, o visualizador procura, na sequência:

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

Depuração remota com metadados personalizados

Ao depurar remotamente, o processo .exe não é local, portanto a busca por metadados personalizados (mencionada na seção anterior) falha. Nesse caso, o visualizador recorre a uma pasta de cache local (%TEMP%) em busca de um arquivo .winmd adequado. Se encontrar algum, ele registra o tamanho e a data do arquivo e, em seguida, procura no destino de depuração remota o mesmo .winmd junto com o binário. Se necessário, o arquivo remoto será baixado, atualizando o cache local. Essa estratégia garante que o cache .winmd local esteja sempre atualizado, além de fornecer um meio para armazenar em cache manualmente um . winmd caso não seja possível encontrá-lo remotamente (por exemplo, se a implantação de F5 não o colocou nele).

Para obter um exemplo do comportamento de cache, consulte a seção Solução de problemas abaixo.

Troubleshooting

O visualizador de depuração usa o avaliador de expressão C++ Visual Studio para invocar a função WINRT_abi_val exportada para obter valores de propriedade. Normalmente, o visualizador pode capturar exceções sem tratamento e degradar normalmente, exibindo "<Objeto não inicializado ou informações indisponíveis>" nas janelas do Visual Studio Watch.

Isso é útil quando o visualizador tenta avaliar uma variável local fora de seu escopo de tempo de vida (por exemplo, antes da construção). Em alguns contextos, como testes de unidade, é instalado um filtro para exceções não tratadas. Isso pode fazer com que o processo seja encerrado quando o avaliador de expressão C++ falhar. Para evitar falhas, o visualizador faz várias chamadas do VirtualQuery em WINRT_abi_val.

Diagnóstico

Se uma propriedade não estiver sendo exibida corretamente, ative o diagnóstico detalhado do Natvis no Visual Studio (Ferramentas>Opções>Depuração>Janela de Saída>Mensagens de diagnóstico do Natvis) e observe a Janela de Saída em busca de erros do Natvis.

O trecho a seguir mostra várias tentativas de investigação de um .winmd arquivo, seguidas por um download do destino remoto para a pasta de cache local e, em seguida, uma carga desse .winmd arquivo.

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

Se o visualizador não encontrar um .winmd arquivo, esse erro será gerado:

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

Há vários outros cenários de erro que produzem diagnósticos.

Se os metadados estiverem disponíveis, o diagnóstico de saída mostrará muitas chamadas 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

A primeira é uma chamada a IStringable.ToString para obter a representação em cadeia de caracteres de um tipo complexo (o valor de exibição não expandido).

A segunda é uma chamada para IInspectable::GetRuntimeClassName, a fim de refletir sobre as propriedades do tipo.

As chamadas subsequentes a WINRT_abi_val são avaliações das propriedades de cada interface descoberta no tipo.

Invocando WINRT_abi_val

Você pode usar as janelas Immediate/Command do Visual Studio para invocar diretamente WINRT_abi_val para diagnosticar problemas.

Por exemplo, considerando uma variável projetada stringable, você pode avaliar IStringable.ToString da seguinte forma:

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