Générer du code source à partir d’assemblys .NET pendant le débogage

Lorsque vous déboguez une application .NET, vous pourriez vouloir afficher le code source que vous n’avez pas. Par exemple, l’arrêt sur une exception ou l’utilisation de la pile des appels pour accéder à un emplacement source.

Notes

  • La génération de code source (décompilation) est uniquement disponible pour les applications .NET et est basée sur le projet ILSpy open source.
  • La décompilation est disponible uniquement dans Visual Studio 2019 version 16.5 et ultérieures.
  • L’application de l’attribut SuppressIldasmAttribute à un assembly ou à un module empêche Visual Studio de tenter la décompilation. Bien que l’attribut soit obsolète dans .NET 6 et les versions ultérieures, Visual Studio le respecte.

Générer le code source

Quand vous déboguez et que le code source n’est pas disponible, Visual Studio affiche le document Source introuvable ou, si vous n’avez pas de symboles pour l’assembly, le document Aucun symbole chargé. Les deux documents ont une option Décompiler le code source qui génère du code C# pour l’emplacement actuel. Le code C# généré peut ensuite être utilisé comme n’importe quel autre code source. Vous pouvez voir le code, inspecter des variables, définir des points d’arrêt, etc.

Aucun symbole chargé

L’illustration suivante montre le message Aucun symbole chargé.

Capture d’écran du document Aucun symbole chargé

Source introuvable

L’illustration suivante montre le message Source introuvable.

Capture d’écran du document Source introuvable

Autodécompiler le code

À partir de la version 17.7 de Visual Studio 2022, le débogueur de Visual Studio prend en charge l’autodécompilation du code .NET externe. Vous pouvez autodécompiler lorsque vous passez dans du code externe ou lorsque vous utilisez la fenêtre de la pile d’appels.

Si vous passez dans du code qui a été implémenté de manière externe, le débogueur le décompile automatiquement et affiche le point d’exécution actuel. Si vous souhaitez passer dans du code externe, désactivez Just My Code.

Vous pouvez décompiler depuis la fenêtre de la pile d’appels sans désactiver Just My Code.

Pour autodécompiler depuis la fenêtre de la pile d’appels :

  1. Lors du débogage avec la fenêtre de la pile d’appels ouverte, sélectionnez Afficher le code externe.

  2. Dans la fenêtre de la pile d’appels, double-cliquez sur n’importe quel cadre de la pile. Le débogueur décompile le code, puis navigue directement jusqu’au point d’exécution actuel.

    Capture d’écran de la fenêtre Pile des appels montrant le code externe.

    Tout le code décompilé est également affiché sous le nœud Sources externes dans l’Explorateur de solutions, ce qui facilite la navigation dans les fichiers externes si nécessaire.

    Capture d’écran du nœud Sources externes montrant les assemblys décompilés.

    Vous pouvez déboguer le code décompilé et définir des points d’arrêt.

Pour désactiver la décompilation automatique du code externe, allez dans Outils > Options > Débogage > Général et désélectionnez Décompiler automatiquement en code source lorsque nécessaire (uniquement géré).

Générer et incorporer des sources pour un assembly

En plus de générer du code source pour un emplacement spécifique, vous pouvez générer tout le code source d’un assembly .NET donné. Pour effectuer cette tâche, accédez à la fenêtre Modules et, dans le menu contextuel d’un assembly .NET, sélectionnez la commande Décompiler la source dans un fichier de symboles. Visual Studio génère un fichier de symboles pour l’assembly, puis incorpore la source dans le fichier de symboles. Par la suite, vous pouvez extraire le code source incorporé.

Capture d’écran du menu contextuel de l’assembly dans la fenêtre Modules avec la commande de décompilation de la source.

Extraire et voir le code source incorporé

Vous pouvez extraire des fichiers sources incorporés dans un fichier de symboles en utilisant la commande Extraire le code source dans le menu contextuel de la fenêtre Modules.

Capture d’écran du menu contextuel de l’assembly dans la fenêtre Modules avec la commande d’extraction des sources.

Les fichiers sources extraits sont ajoutés à la solution comme des fichiers divers. La fonctionnalité de fichiers divers est désactivée par défaut dans Visual Studio. Vous pouvez activer cette fonctionnalité en cochant la case Outils>Options>Environnement>Documents>Afficher les fichiers divers dans l’Explorateur de solutions. Si cette fonctionnalité n’est pas activée, vous ne pouvez pas ouvrir le code source extrait.

Capture d’écran de la page d’options des outils avec l’option Fichiers divers activée.

Les fichiers sources extraits s’affichent dans les fichiers divers dans l’Explorateur de solutions.

Capture d’écran de l’Explorateur de solutions avec des fichiers divers.

Pour les bibliothèques .NET ou pour les packages NuGet activés pour SourceLink, vous pouvez également effectuer un pas à pas détaillé du code source, définir des points d’arrêt et utiliser toutes les fonctionnalités du débogueur. Pour plus d’informations, consultez Activer le débogage et les diagnostics avec Source Link et Improving debug-time productivity with SourceLink.

Limitations connues

Nécessite le mode arrêt

La génération de code source en utilisant la décompilation est possible seulement quand le débogueur est en mode arrêt et que l’application est en pause. Par exemple, Visual Studio passe en mode arrêt quand il atteint un point d’arrêt ou une exception. Vous pouvez facilement déclencher l’arrêt de Visual Studio la prochaine fois que votre code s’exécute en utilisant la commande Tout arrêter (icône Tout arrêter).

Limitations de la décompilation

La génération de code source à partir du format intermédiaire (IL) utilisé dans les assemblys .NET présente certaines limitations inhérentes. Par conséquent, le code source généré ne ressemble pas au code source d’origine. La plupart des différences concernent les informations du code source d’origine qui ne sont pas nécessaires au moment de l’exécution. Par exemple, les informations comme les espaces blancs, les commentaires et les noms des variables locales ne sont pas nécessaires au moment de l’exécution. Nous vous recommandons d’utiliser la source générée pour comprendre comment le programme s’exécute et non pour remplacer le code source d’origine.

Déboguer des assemblys optimisés ou Release

Pendant le débogage du code décompilé à partir d’un assembly compilé à l’aide des optimisations du compilateur, vous pourriez rencontrer les problèmes suivants :

  • Les points d’arrêt pourraient ne pas toujours être liés à l’emplacement d’approvisionnement correspondant.
  • L’exécution pas à pas pourrait ne pas toujours atteindre l’emplacement approprié.
  • Les variables locales pourraient ne pas avoir de noms précis.
  • Certaines variables pourraient ne pas être disponibles pour l’évaluation.

Pour plus d’informations, consultez le problème GitHub : Intégration d’ICSharpCode.Decompiler au Débogueur VS.

Fiabilité de la décompilation

Un pourcentage relativement faible de tentatives de décompilation peut entraîner un échec. Ce comportement est dû à une erreur de référence null du point de séquence dans ILSpy. Nous avons atténué l’échec en interceptant ces problèmes et en faisant échouer normalement la tentative de décompilation.

Pour plus d’informations, consultez le problème GitHub : Intégration d’ICSharpCode.Decompiler au Débogueur VS.

Limitations avec le code asynchrone

Les résultats de la décompilation des modules avec des modèles de code async/await pourraient être incomplets ou échouer entièrement. L’implémentation ILSpy des modèles async/await et des machines à états yield n’est que partiellement effectuée.

Pour plus d’informations, consultez le problème GitHub : État du générateur PDB.

Uniquement mon code

Le paramètre Uniquement mon code (JMC) permet à Visual Studio de faire un pas à pas principal des appels du système, du framework, de la bibliothèque et d’autres appels non-utilisateur. Au cours d’une session de débogage, la fenêtre Modules indique les modules de code que le débogueur traite comme Mon code (code utilisateur).

La décompilation des modules optimisés ou Release génère du code non-utilisateur. Si le débogueur s’arrête dans votre code non-utilisateur décompilé, par exemple, la fenêtre Aucune source s’affiche. Pour désactiver Uniquement mon code, accédez à Outils>Options (ou Déboguer>Options) >Débogage>Général, puis décochez Activer Uniquement mon code.

Sources extraites

Le code source extrait d’un assembly a les limitations suivantes :

  • Le nom et l’emplacement des fichiers générés ne sont pas configurables.
  • Les fichiers sont temporaires et supprimés par Visual Studio.
  • Les fichiers sont placés dans un seul dossier et la hiérarchie de dossiers précédente des sources d’origine n’est pas utilisée.
  • Le nom de chaque fichier contient un hachage de somme de contrôle du fichier.

Le code généré est C# uniquement

La décompilation génère uniquement des fichiers de code source en C#. Il n’existe aucune option pour générer des fichiers dans un autre langage.