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#.

Observação

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

Como habilitar o Natvis

O Natvis é ativado automaticamente para um build de depuração porque o WINRT_NATVIS é definido quando o símbolo _DEBUG é definido.

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

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

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

Como usar metadados personalizados

O visualizador de depuração procura os metadados definidos pelo usuário (arquivos .winmd) junto com o 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

Durante a depuração remota, o processo .exe não é local. Portanto, ocorre uma falha na pesquisa de metadados personalizados (mencionada na seção anterior). Nesse caso, o visualizador recorre a uma pasta de cache local (%TEMP%) para encontrar um arquivo .winmd adequado. Se encontrar um, ele registrará o tamanho e a data do arquivo e pesquisará 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 .winmd armazenado em cache local seja sempre atualizado, bem como garante o fornecimento de um meio para o armazenamento em cache manual de 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, confira a seção Solução de problemas abaixo.

Solução de problemas

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

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

Diagnósticos

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 arquivo .winmd, seguido por um download do destino remoto para a pasta de cache local e um carregamento desse arquivo .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

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

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

Há vários outros cenários de erros 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 de cadeia de caracteres de um tipo complexo (o valor de exibição não expandido).

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

As chamadas de WINRT_abi_val posteriores são avaliações de propriedade para cada interface descoberta no tipo.

Como invocar o WINRT_abi_val

Use as janelas Imediata/Comando do Visual Studio para invocar WINRT_abi_val diretamente para a solução de problemas.

Por exemplo, considerando uma variável projetada stringable, você pode avaliar a respectiva IStringable.ToString como:

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