Gerar código-fonte de assemblies .NET durante a depuração

Ao depurar uma aplicativo .NET, você pode encontrar uma situação em que deseja exibir um código-fonte que não possui. Por exemplo, interrompendo uma exceção ou usando a pilha de chamadas para navegar até um local de origem.

Observação

  • A geração de código-fonte (descompilação) só está disponível para aplicativos .NET e se baseia no projeto ILSpy de código aberto.
  • A descompilação só está disponível no Visual Studio 2019 16.5 e posterior.
  • A aplicação do atributo SuppressIldasmAttribute a um assembly ou módulo impede que o Visual Studio tente descompilar. Embora o atributo esteja obsoleto no .NET 6 e posterior, o Visual Studio respeita o atributo.

Gerar código-fonte

Quando você está depurando e nenhum código-fonte está disponível, o Visual Studio mostra o documento Origem Não Encontrada ou, se você não tiver símbolos para o assembly, o documento Nenhum Símbolo Carregado. Ambos os documentos têm uma opção Descompilar código-fonte que gera código C# para o local atual. O código C# gerado pode ser usado como qualquer outro código-fonte. Você pode exibir o código, inspecionar variáveis, definir pontos de interrupção e assim por diante.

Sem símbolos carregados

A ilustração a seguir mostra a mensagem Nenhum Símbolo Carregado.

Screenshot of no symbol loaded document

Origem não encontrada

A ilustração a seguir mostra a mensagem Origem Não Encontrada.

Screenshot of source not found document

Código de compilação automática

A partir do Visual Studio 2022 versão 17.7, o depurador do Visual Studio dá suporte à descompilação automática de código .NET externo. Você pode descompilar automaticamente ao entrar no código externo ou usando a janela Pilha de chamadas.

Se você intervir no código que foi implementado externamente, o depurador o descompila automaticamente e exibe o ponto de execução atual. Se você quiser entrar no código externo, o Apenas Meu Código deve ser desabilitado.

Você pode descompilar facilmente a partir da janela Pilha de Chamadas sem desativar Apenas Meu Código.

Para descompilar automaticamente na janela Pilha de chamadas:

  1. Ao depurar com a janela Pilha de chamadas aberta, selecione Mostrar código externo.

  2. Na janela Pilha de chamadas, clique duas vezes em qualquer quadro da pilha. O depurador descompila o código e navega diretamente para o ponto atual de execução.

    Screenshot of Call Stack window showing external code.

    Todo o código descompilado também é mostrado no nó Fontes Externas do Gerenciador de Soluções, facilitando a navegação pelos arquivos externos, se necessário.

    Screenshot of External Sources node showing decompiled assemblies.

    Você pode depurar o código descompilado e definir pontos de interrupção.

Para desativar a descompilação automática de código externo, vá para Ferramentas > Opções > Depuração > General e desmarque Descompilar automaticamente para o código-fonte quando necessário (somente gerenciado).

Gerar e inserir fontes para um assembly

Além de gerar o código-fonte para um local específico, você pode gerar todo o código-fonte para um determinado assembly do .NET. Para realizar essa tarefa, acesse a janela Módulos e, no menu de contexto de um assembly .NET, selecione o comando Descompilar Origem para Arquivo de Símbolo. O Visual Studio gera um arquivo de símbolo para o assembly e insere a fonte no arquivo de símbolo. Em uma etapa posterior, você pode extrair o código-fonte inserido.

Screenshot of assembly context menu in modules window with decompile source command.

Extrair e exibir o código-fonte inserido

Você pode extrair arquivos de origem inseridos em um arquivo de símbolo usando o comando Extrair Código-Fonte no menu de contexto da janela Módulos.

Screenshot of assembly context menu in modules window with extract sources command.

Os arquivos de origem extraídos são adicionados à solução como arquivos diversos. O recurso de arquivos diversos está desativado por padrão no Visual Studio. Você pode habilitar esse recurso na caixa de seleção Ferramentas>Opções>Ambiente>Documentos>Mostrar arquivos diversos no Gerenciador de Soluções. Se esse recurso não estiver habilitado, você não poderá abri o código-fonte extraído.

Screenshot of tools option page with miscellaneous files option enabled.

Os arquivos de origem extraídos aparecem nos arquivos diversos em Gerenciador de Soluções.

Screenshot of solution explorer with miscellaneous files.

Para bibliotecas .NET ou pacotes NuGet habilitados para SourceLink, você também pode intervir no código-fonte, definir pontos de interrupção e usar todos os recursos do depurador. Para obter mais informações, consulte Habilitar depuração e diagnóstico com o Link de Origem e Melhorar a produtividade em tempo de depuração com o SourceLink.

Limitações conhecidas

Requer o modo de interrupção

A geração de código-fonte usando a descompilação só é possível quando o depurador está no modo de interrupção e o aplicativo está em pausa. Por exemplo, o Visual Studio entra no modo de interrupção quando atinge um ponto de interrupção ou uma exceção. Você pode disparar facilmente o Visual Studio para interromper na próxima vez que o código for executado usando o comando Interromper Tudo (Break all icon).

Limitações de descompilação

A geração de código-fonte do IL (formato intermediário) usado em assemblies .NET tem algumas limitações inerentes. Dessa forma, o código-fonte gerado não se parece com o código-fonte original. A maioria das diferenças está em locais em que as informações no código-fonte original não são necessárias no runtime. Por exemplo, informações como espaço em branco, comentários e nomes de variáveis locais não são necessárias em runtime. Recomendamos que você use a fonte gerada para entender como o programa está sendo executado e não como uma substituição para o código-fonte original.

Depurar assemblies otimizados ou da versão

Ao depurar o código descompilado de um assembly que foi compilado utilizando otimizações do compilador, você pode se deparar com os seguintes problemas:

  • Os pontos de interrupção podem nem sempre ser vinculados à localização de origem correspondente.
  • As etapas podem nem sempre ir para o local correto.
  • As variáveis locais podem não ter nomes precisos.
  • Algumas variáveis podem não estar disponíveis para avaliação.

Mais detalhes podem ser encontrados no problema do GitHub: integração do ICSharpCode.Decompiler ao Depurador VS.

Confiabilidade de descompilação

Uma porcentagem relativamente pequena de tentativas de descompilação pode resultar em falha. Esse comportamento se deve a um erro de referência nula de ponto de sequência no ILSpy. Atenuamos a falha capturando esses problemas e falhando na tentativa de descompilação.

Mais detalhes podem ser encontrados no problema do GitHub: integração do ICSharpCode.Decompiler ao Depurador VS.

Limitações com código assíncrono

Os resultados da descompilação de módulos com padrões de código async/await podem estar incompletos ou falhar totalmente. A implementação do ILSpy de máquinas de estado assíncronas/await e de rendimento é implementada apenas parcialmente.

Mais detalhes podem ser encontrados no problema do GitHub: Status do Gerador PDB.

Apenas Meu Código

A configuração Apenas Meu Código (JMC) permite que o Visual Studio passe por cima de chamadas de sistema, estrutura, biblioteca e outras chamadas não-usuário. Durante uma sessão de depuração, a janela Módulos mostra quais módulos de código o depurador está tratando como Meu Código (código do usuário).

A descompilação de módulos otimizados ou de versões produz o código não-usuário. Se o depurador interromper o código não-usuário. descompilado, por exemplo, aparecerá a janela Sem Origem. Para desabilitar Apenas Meu Código, navegue até Ferramentas>Opções (ou Depurar>Opções) >Depurando>Geral e desmarque Habilitar Apenas Meu Código.

Fontes extraídas

O código-fonte extraído de um assembly tem as seguintes limitações:

  • O nome e o local dos arquivos gerados não são configuráveis.
  • Os arquivos são temporários e excluídos pelo Visual Studio.
  • Os arquivos são colocados em uma única pasta e qualquer hierarquia de pastas que as fontes originais tinham não é usada.
  • O nome do arquivo para cada arquivo contém um hash de soma de verificação do arquivo.

O código gerado é apenas C#

A descompilação gera apenas arquivos de código-fonte em C#. Não existe uma opção para gerar arquivos em qualquer outra linguagem.