Déboguer uniquement le code utilisateur avec Uniquement mon code

Uniquement mon code est une fonctionnalité de débogage de Visual Studio qui exécute automatiquement un pas à pas principal sur les appels au système, au framework et au reste du code non-utilisateur. Dans la fenêtre Pile des appels, Uniquement mon code réduit ces appels dans des frames [External Code].

Uniquement mon code fonctionne différemment dans les projets .NET et C++.

Activer ou désactiver Uniquement mon code

Pour la plupart des langages de programmation, Uniquement mon code est activé par défaut.

  • Pour activer ou désactiver Uniquement mon code dans Visual Studio, sous Outils>Options (ou Déboguer>Options) >Débogage>Général, cochez ou décochez Activer Uniquement mon code.

Capture d’écran de l’option Activer Uniquement mon code dans la boîte de dialogue Options.

Capture d’écran de l’option Activer Uniquement mon code dans la boîte de dialogue Options.

Notes

Activer Uniquement mon code est un paramètre général qui s’applique à tous les projets Visual Studio dans tous les langages.

Uniquement mon code (débogage)

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), ainsi que l’état de chargement de leurs symboles. Pour plus d’informations, consultez Se familiariser avec l’attachement du débogueur à votre application.

Capture d’écran du code utilisateur dans la fenêtre Modules.

Capture d’écran du code utilisateur dans la fenêtre Modules.

Dans la fenêtre Pile des appels ou Tâches, Uniquement mon code réduit le code non-utilisateur dans un frame de code annoté grisé et étiqueté [External Code].

Capture d’écran d’External Code dans la fenêtre Pile des appels.

Capture d’écran d’External Code dans la fenêtre Pile des appels.

Conseil

Pour ouvrir les fenêtres Modules, Pile des appels, Tâches ou la plupart des autres fenêtres de débogage, vous devez être dans une session de débogage. Pendant le débogage, sous Déboguer>Fenêtres, sélectionnez les fenêtres que vous souhaitez ouvrir.

Pour voir le code dans un frame [External Code] réduit, cliquez avec le bouton droit dans la fenêtre Pile des appels ou Tâche, puis sélectionnez Afficher le code externe dans le menu contextuel. Les lignes de code externe développées remplacent le frame [External Code].

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

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

Notes

Afficher le code externe est un paramètre du profil utilisateur actuel qui s’applique à tous les projets dans tous les langages ouverts par l’utilisateur.

Un double-clic sur une ligne de code externe développée dans la fenêtre Pile des appels met en évidence la ligne de code appelante en vert dans le code source. Pour les DLL ou d’autres modules introuvables ou chargés, une page introuvable source ou de symboles peut s’ouvrir.

À partir de la version 17.7 de Visual Studio 2022, vous pouvez décompiler automatiquement le code .NET en double-cliquant sur du code externe dans la fenêtre de la pile d’appels. Pour plus d’informations, veuillez consulter la rubrique Générer du code source à partir des assemblies .NET lors du débogage.

Uniquement mon code .NET

Dans les projets .NET, Uniquement mon code utilise des fichiers de symboles (.pdb) et des optimisations de programme pour classer le code utilisateur et non-utilisateur. Le débogueur .NET considère que les fichiers binaires optimisés et les fichiers .pdb non chargés sont du code non-utilisateur.

Trois attributs de compilateur affectent également ce que le débogueur .NET considère comme du code utilisateur :

  • DebuggerNonUserCodeAttribute indique au débogueur que le code auquel il est appliqué n’est pas du code utilisateur.
  • DebuggerHiddenAttribute masque le code au débogueur, même si l'option Uniquement mon code est désactivée.
  • DebuggerStepThroughAttribute indique au débogueur d’exécuter pas à pas le code auquel il est appliqué, plutôt que de faire un pas à pas détaillé du code.

Le débogueur .NET considère tous le reste du code comme du code utilisateur.

Pendant le débogage .NET :

  • Déboguer>Effectuer un pas à pas détaillé (ou F11) sur du code non-utilisateur effectue un pas à pas du le code jusqu’à la ligne suivante du code utilisateur.
  • Déboguer>Pas à pas sortant (ou Maj+F11) sur du code non-utilisateur s’exécute jusqu’à la ligne suivante du code utilisateur.

S’il n’y a plus de code utilisateur, le débogage continue jusqu’à ce qu’il se termine, qu’il atteigne un autre point d’arrêt ou qu’il génère une erreur.

Si le débogueur s’arrête dans du code non-utilisateur (par exemple, vous utilisez Déboguer>Tout arrêter et faites une pause dans du code non-utilisateur), la fenêtre Aucune source s’affiche. Vous pouvez ensuite utiliser une commande Déboguer>Exécuter pas à pas pour accéder à la ligne suivante de code utilisateur.

Si une exception non gérée se produit dans du code non-utilisateur, le débogueur s’arrête à la ligne de code utilisateur où l’exception a été générée.

Si les exceptions de première chance sont activées pour l’exception, la ligne de code utilisateur appelante est mise en surbrillance en vert dans le code source. La fenêtre Pile des appels affiche le frame annoté étiqueté [External Code].

Uniquement mon code C++

À compter de Visual Studio 2017 version 15.8, Uniquement mon code est également pris en charge pour l’exécution pas à pas du code. Cette fonctionnalité nécessite également le commutateur de compilateur /JMC (débogage Uniquement mon code). Le commutateur est activé par défaut dans les projets C++. Pour la fenêtre Pile d’appels et la prise en charge de la pile d’appels dans Just My Code, l’option /JMC n’est pas requise.

Pour être classé comme du code utilisateur, le PDB du fichier binaire contenant le code utilisateur doit être chargé par le débogueur (utilisez la fenêtre Modules pour le vérifier).

Pour le comportement de la pile d’appels, comme dans la fenêtre Pile des appels, Uniquement mon code en C++ considère ces fonctions uniquement comme du code non-utilisateur :

  • Fonctions avec des informations sources supprimées dans leur fichier de symboles.
  • Les fonctions pour lesquelles les fichiers de symboles indiquent qu’il n’y a pas de fichier source correspondant au cadre de la pile.
  • Fonctions spécifiées dans les fichiers *.natjmc dans le dossier %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers.

Pour le comportement d’exécution pas à pas du code, Uniquement mon code en C++ considère ces fonctions uniquement comme du code non-utilisateur :

  • Les fonctions pour lesquelles le fichier PDB correspondant n’a pas été chargé dans le débogueur.
  • Fonctions spécifiées dans les fichiers *.natjmc dans le dossier %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers.

Notes

Pour la prise en charge de l’exécution pas à pas du code dans Uniquement mon code, le code C++ doit être compilé avec les compilateurs MSVC dans Visual Studio 15.8 Preview 3 ou version ultérieure, et le commutateur de compilateur /JMC doit être activé (il est activé par défaut). Pour plus d’informations, consultez Personnaliser le comportement de la pile d’appels C++ et de l’exécution pas à pas du code et ce billet de blog. Pour le code compilé avec un compilateur plus ancien, les fichiers .natstepfilter sont le seul moyen de personnaliser l’exécution pas à pas du code, qui est indépendante de Uniquement mon code. Consultez Personnaliser le comportement de l’exécution pas à pas du code C++.

Pendant le débogage C++, le code non utilisateur est ignoré par défaut. Pendant le débogage C++ :

  • Déboguer>Pas à pas détaillé (ou F11) sur les étapes de code non utilisateur passe au-dessus du code ou s’exécute sur la ligne suivante du code utilisateur, si Pas à pas détaillé est appelé à partir de code non-utilisateur.
  • Déboguer>Pas à pas sortant (ou Maj+F11) sur le code non utilisateur s’exécute sur la ligne suivante de code utilisateur (en dehors du cadre de pile actuel).

S’il n’y a plus de code utilisateur, le débogage continue jusqu’à ce qu’il se termine, qu’il atteigne un autre point d’arrêt ou qu’il génère une erreur.

Si le débogueur s’arrête dans du code non-utilisateur (par exemple, vous utilisez Déboguer>Tout arrêter et faites une pause dans du code non-utilisateur), l’exécution pas à pas du code continue dans le code non-utilisateur.

Quand le débogueur rencontre une exception, il s’arrête sur l’exception, qu’il s’agisse de code utilisateur ou non-utilisateur. Les options Non gérée par l’utilisateur de la boîte de dialogue Paramètres des exceptions sont ignorées.

Personnaliser le comportement de la pile d’appels C++ et de l’exécution pas à pas du code

Pour les projets C++, vous pouvez spécifier les modules, les fichiers sources et les fonctions que la fenêtre Pile des appels traite comme du code non-utilisateur en les spécifiant dans des fichiers *.natjmc. Cette personnalisation s’applique également à la progression du code si vous utilisez le compilateur le plus récent (voir Just My Code C++).

  • Pour spécifier du code non-utilisateur pour tous les utilisateurs de la machine Visual Studio, ajoutez le fichier .natjmc au dossier %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers.
  • Pour spécifier du code non-utilisateur pour un utilisateur individuel, ajoutez le fichier .natjmc au dossier %USERPROFILE%\My Documents\<version Visual Studio>\Visualizers.

Un fichier .natjmc est un fichier XML avec la syntaxe suivante :

<?xml version="1.0" encoding="utf-8"?>
<NonUserCode xmlns="http://schemas.microsoft.com/vstudio/debugger/jmc/2015">

  <!-- Modules -->
  <Module Name="ModuleSpec" />
  <Module Name="ModuleSpec" Company="CompanyName" />

  <!-- Files -->
  <File Name="FileSpec"/>

  <!-- Functions -->
  <Function Name="FunctionSpec" />
  <Function Name="FunctionSpec" Module ="ModuleSpec" />
  <Function Name="FunctionSpec" Module ="ModuleSpec" ExceptionImplementation="true" />

</NonUserCode>

Attributs des éléments Module

Attribut Description
Name Obligatoire. Chemin d’accès complet du ou des modules. Vous pouvez utiliser les caractères génériques Windows ? (zéro ou un caractère) et * (zéro ou plusieurs caractères). Par exemple,

<Module Name="?:\3rdParty\UtilLibs\*" />

indique au débogueur de traiter tous les modules dans \3rdParty\UtilLibs sur n’importe quel lecteur comme du code externe.
Company facultatif. Le nom de la société qui publie le module incorporé dans le fichier exécutable. Vous pouvez utiliser cet attribut pour lever l'ambiguïté entre les modules.

Attributs des éléments File

Attribut Description
Name Obligatoire. Chemin d’accès complet du ou des fichiers sources à traiter comme du code externe. Vous pouvez utiliser les caractères génériques Windows ? et * quand vous spécifiez le chemin d’accès.

Attributs des éléments Function

Attribut Description
Name Obligatoire. Le nom complet de la fonction à traiter comme du code externe. Vous pouvez utiliser les caractères génériques Windows ? et * lorsque vous spécifiez le chemin d’accès.
Module Facultatif. Le nom ou le chemin d'accès complet au module qui contient la fonction. Vous pouvez utiliser cet attribut pour lever l'ambiguïté entre des fonctions du même nom.
ExceptionImplementation Quand la valeur est définie sur true, la pile des appels affiche la fonction qui a levé l'exception, au lieu de cette fonction.

Personnaliser le comportement d’exécution pas à pas du code C++ indépendamment des paramètres Uniquement mon code

Dans les projets C++, vous pouvez spécifier des fonctions à exécuter pas à pas en les listant comme des fonctions NoStepInto dans les fichiers *.natstepfilter. Les fonctions répertoriées dans les fichiers *.natstepfilter ne dépendent pas des paramètres Just My Code. Une fonction NoStepInto indique au débogueur d’effectuer un pas à pas sur la fonction, même si elle appelle des fonctions « StepInto» ou d’autres codes utilisateur. Contrairement aux fonctions répertoriées dans .natjmc, le débogueur effectue un pas à pas détaillé sur la première ligne de code utilisateur à l’intérieur de la fonction NoStepInto.

  • Pour spécifier du code non-utilisateur pour tous les utilisateurs de l’instance Visual Studio locale, ajoutez le fichier .natstepfilter au dossier %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers.
  • Pour spécifier du code non-utilisateur pour un utilisateur individuel, ajoutez le fichier .natstepfilter au dossier %USERPROFILE%\My Documents\<version Visual Studio>\Visualizers.

Note

Certaines extensions tierces peuvent désactiver la fonctionnalité .natstepfilter .

Un fichier .natstepfilter est un fichier XML avec la syntaxe suivante :

<?xml version="1.0" encoding="utf-8"?>
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">
    <Function>
        <Name>FunctionSpec</Name>
        <Action>StepAction</Action>
    </Function>
    <Function>
        <Name>FunctionSpec</Name>
        <Module>ModuleSpec</Module>
        <Action>StepAction</Action>
    </Function>
</StepFilter>

Élément Description
Function Obligatoire. Spécifie une ou plusieurs fonctions comme fonctions non-utilisateur.
Name Obligatoire. Une expression régulière mise en forme selon ECMA-262 spécifiant le nom complet de la fonction concernée. Par exemple :

<Name>MyNS::MyClass::.*</Name>

indique au débogueur que toutes les méthodes de MyNS::MyClass doivent être considérées comme du code non-utilisateur. La recherche de correspondance respecte la casse.
Module facultatif. Une expression régulière mise en forme selon ECMA-262 spécifiant le chemin d'accès complet au module contenant la fonction. La recherche de correspondance ne respecte pas la casse.
Action Obligatoire. Une des valeurs suivantes (respectant la casse) :

NoStepInto : indique au débogueur d’exécuter pas à pas la fonction concernée.
StepInto : indique au débogueur d’exécuter un pas à pas détaillé de la fonction, en remplaçant tous les paramètres NoStepInto de la fonction concernée.

Informations supplémentaires sur les fichiers .natstepfilter et .natjmc

  • À compter de Visual Studio 2022 version 17.6, vous pouvez ajouter des fichiers .natjmc et .natstepfilter directement à la solution ou au projet.

  • Les erreurs de syntaxe dans les fichiers .natstepfilter et .natjmc ne sont pas signalées dans la fenêtre de sortie du débogueur.

  • Contrairement aux fichiers .natvis, les fichiers .natstepfilter et .natjmc ne sont pas rechargés à chaud. Au lieu de cela, ces fichiers sont rechargés près du début de la session de débogage.

  • Pour les fonctions de modèle, l’utilisation de &lt;.*&gt; ou &lt;.* dans le nom peut être utile.

Uniquement mon code JavaScript

Uniquement mon code JavaScript contrôle l’exécution pas à pas et l’affichage de la pile des appels en catégorisant le code selon la classification suivante :

classification ; Description
MyCode Code utilisateur dont vous êtes propriétaire et que vous contrôlez.
LibraryCode Code non-utilisateur provenant de bibliothèques que vous utilisez régulièrement et dont dépend le fonctionnement de votre application (par exemple jQuery).
UnrelatedCode Code non-utilisateur dans votre application dont vous n’êtes pas le propriétaire et dont le fonctionnement de votre application ne dépend pas. Par exemple, un SDK publicitaire qui affiche des annonces peut être classé comme UnrelatedCode.

Le débogueur JavaScript classe le code comme étant utilisateur ou non-utilisateur dans cet ordre :

  1. Classifications par défaut.

    • Un script exécuté en passant une chaîne à la fonction eval fournie par l’hôte est classé dans MyCode.
    • Un script exécuté en passant une chaîne au constructeur Function est classé dans LibraryCode.
    • Un script dans une référence de framework, comme WinJS ou le SDK Azure, est classé dans LibraryCode.
    • Un script exécuté en passant une chaîne aux fonctions setTimeout, setImmediate ou setInterval est classé dans UnrelatedCode.
  2. Classifications dans le fichier mycode.json du projet actuel.

Chaque étape de classification remplace les étapes précédentes.

Le reste du code est classé comme MyCode.

Vous pouvez modifier les classifications par défaut, et classer des fichiers et des URL spécifiques comme du code utilisateur ou non-utilisateur en ajoutant un fichier .json nommé mycode.json au dossier racine d’un projet JavaScript. Consultez Personnaliser Uniquement mon code JavaScript.

Pendant le débogage JavaScript :

  • Si une fonction est du code non-utilisateur, Déboguer>Effectuer un pas à pas détaillé (ou F11) se comporte comme Déboguer>Pas à pas principal (ou F10).
  • Si une étape commence dans du code non-utilisateur (LibraryCode ou UnrelatedCode), l’exécution pas à pas se comporte temporairement comme si Uniquement mon code n’était pas activé. Dès que vous revenez à du code utilisateur, Uniquement mon code est réactivé.
  • Quand une exécution pas à pas de code utilisateur amène à quitter le contexte d’exécution actuel, le débogueur s’arrête sur la ligne de code utilisateur exécutée suivante. Par exemple, si un rappel s’exécute dans du code LibraryCode, le débogueur continue jusqu’à ce que la ligne suivante du code utilisateur s’exécute.
  • Pas à pas sortant (ou Maj+F11) s’arrête sur la ligne de code utilisateur suivante.

S’il n’y a plus de code utilisateur, le débogage continue jusqu’à ce qu’il se termine, qu’il atteigne un autre point d’arrêt ou qu’il génère une erreur.

Les points d’arrêt définis dans le code sont toujours atteints, mais le code est classifié.

  • Si le mot clé debugger se produit dans LibraryCode, le débogueur s’arrête toujours.
  • Si le mot clé debugger se produit dans UnrelatedCode, le débogueur ne s’arrête pas.

Si une exception non gérée se produit dans du code MyCode ou LibraryCode, le débogueur s’arrête toujours.

Si une exception non gérée se produit dans UnrelatedCode, et que du code MyCode ou LibraryCode est dans la pile des appels, le débogueur s’arrête.

Si les exceptions de première chance sont activées pour l’exception et que l’exception se produit dans du code LibraryCode ou UnrelatedCode :

  • Si l’exception est gérée, le débogueur ne s’arrête pas.
  • Si l’exception n’est pas gérée, le débogueur s’interrompt.

Personnaliser Uniquement mon code JavaScript

Pour catégoriser le code utilisateur et non-utilisateur d’un seul projet JavaScript, vous pouvez ajouter un fichier .json nommé mycode.json dans le dossier racine du projet.

Le fichier mycode.json n’a pas besoin de lister toutes les paires clé-valeur. Les valeurs MyCode, Libraries et Unrelated peuvent être des tableaux vides.

Les fichiers Mycode.json utilisent cette syntaxe :

{
    "Eval" : "Classification",
    "Function" : "Classification",
    "ScriptBlock" : "Classification",
    "MyCode" : [
        "UrlOrFileSpec",
        . . .
        "UrlOrFileSpec"
    ],
    "Libraries" : [
        "UrlOrFileSpec",
        . .
        "UrlOrFileSpec"
    ],
    "Unrelated" : [
        "UrlOrFileSpec",
        . . .
        "UrlOrFileSpec"
    ]
}

Eval, Function et ScriptBlock

Les paires clé-valeur Eval, Function et ScriptBlock déterminent comment le code généré dynamiquement est classifié :

Nom Description
Eval un script qui est exécuté en passant une chaîne à la fonction eval fournie par l'hôte. Par défaut, le script Eval est classifié comme MyCode.
Fonction un script qui est exécuté en passant une chaîne au constructeur Function. Par défaut, le script Function est classé comme LibraryCode.
ScriptBlock un script qui est exécuté en passant une chaîne aux fonctions setTimeout, setImmediate ou setInterval. Par défaut, le script ScriptBlock est classé comme UnrelatedCode.

Vous pouvez changer la valeur en un de ces mots clés :

  • MyCode classifie le script comme MyCode.
  • Library classifie le script comme LibraryCode.
  • Unrelated classifie le script comme UnrelatedCode.

MyCode, Libraries et Unrelated

Les paires clé-valeur MyCode, Libraries et Unrelated spécifient les URL ou les fichiers que vous voulez inclure dans une classification :

Nom Description
MyCode Un tableau d’URL ou de fichiers qui sont classés comme MyCode.
Bibliothèques Un tableau d’URL ou de fichiers qui sont classifiés comme LibraryCode.
Unrelated Un tableau d’URL ou de fichiers qui sont classés comme UnrelatedCode.

La chaîne d’URL ou de fichier peut avoir un ou plusieurs caractères *, qui correspondent à zéro ou plusieurs caractères. * est identique à l’expression régulière .*.