Debuggen von Benutzercode mit nur eigenem Code

Nur eigenen Code ist ein Visual Studio-Debugfeature, das automatisch Aufrufe von System-, Framework- und anderem Nichtbenutzercode überspringt. Im Fenster Aufrufstapel werden diese Aufrufe von „Nur eigenen Code“ in Frames mit [externem Code] reduziert.

„Nur eigenen Code“ funktioniert in .NET- und C++-Projekten unterschiedlich.

Aktivieren oder Deaktivieren von "Nur eigenen Code"

Für die meisten Programmiersprachen ist „Nur eigenen Code“ standardmäßig aktiviert.

  • Um „Nur eigenen Code“ in Visual Studio zu aktivieren bzw. zu deaktivieren, aktivieren bzw. deaktivieren Sie unter Extras>Optionen (oder Debuggen>Optionen) > >Debugging>Allgemein die Option Nur meinen Code aktivieren.

Screenshot: „Nur eigenen Code aktivieren“ im Dialogfeld „Optionen“

Screenshot: „Nur eigenen Code aktivieren“ im Dialogfeld „Optionen“

Hinweis

Nur meinen Code aktivieren ist eine globale Einstellung, die auf alle Visual Studio-Projekte in allen Sprachen angewendet wird.

Nur mein Code (Debugoption)

Während einer Debugsitzung wird im Fenster Module zusammen mit dem jeweiligen Symbolladestatus angezeigt, welche Codemodule vom Debugger als eigener Code (Benutzercode) behandelt werden. Weitere Informationen erhalten Sie unter Informieren Sie sich darüber, wie der Debugger an Ihre App angefügt wird.

Screenshot: Benutzercode im Fenster „Module“

Screenshot: Benutzercode im Fenster „Module“

Im Fenster Aufrufstapel oder Tasks wird Nichtbenutzercode von „Nur eigenen Code“ in einen grauen, kommentierten Codeframe mit der Bezeichnung [External Code] reduziert.

Screenshot: Externer Code im Fenster „Aufrufliste“

Screenshot: Externer Code im Fenster „Aufrufliste“

Tipp

Zum Öffnen vonModule, Aufrufstapel, Tasks oder der meisten anderen Debugfenster müssen Sie sich in einer Debugsitzung befinden. Wählen Sie während des Debuggens unter Debuggen>Fenster die Fenster aus, die Sie öffnen möchten.

Um den Code in einem reduzierten Frame mit [externem Code] anzuzeigen, klicken Sie mit der rechten Maustaste in das Fenster Aufrufstapel oder Tasks und wählen Sie im Kontextmenü Externen Code anzeigen aus. Die erweiterten externen Codezeilen ersetzen den Frame mit [externem Code] .

Screenshot: „Externen Code anzeigen“ im Fenster „Aufrufliste“

Screenshot: „Externen Code anzeigen“ im Fenster „Aufrufliste“

Hinweis

Externen Code anzeigen ist eine aktuelle Benutzerprofileinstellung, die für alle Projekte in allen Sprachen gilt, die vom Benutzer geöffnet werden.

Durch Doppelklicken auf eine erweiterte externe Codezeile im Fenster Aufrufstapel wird die aufrufende Codezeile im Quellcode in Grün hervorgehoben. Bei DLLs oder anderen Modulen, die nicht gefunden oder geladen wurden, kann sich eine Seite „Symbol oder Quelle nicht gefunden“ öffnen.

Ab Visual Studio 2022, Version 17.7, können Sie .NET-Code automatisch dekompilieren, indem Sie im Fenster „Aufrufliste“ auf externen Code doppelklicken. Weitere Informationen finden Sie unter Generieren von Quellcode aus .NET-Assemblys beim Debuggen.

„Nur eigenen Code“ in .NET

In .NET-Projekten werden von „Nur eigenen Code“ Symboldateien ( . pdb) und Programmoptimierungen verwendet, um Benutzer- und Nichtbenutzercode zu klassifizieren. Der .NET-Debugger betrachtet optimierte Binärdateien und nicht geladene .pdb-Dateien als Nichtbenutzercode.

Drei Compilerattribute beeinflussen außerdem, was der .NET-Debugger als Benutzercode ansieht:

Der .NET-Debugger betrachtet den gesamten anderen Code als Benutzercode.

Beim .NET-Debuggen:

  • Debuggen>Einzelschritt (oder F11) in Nichtbenutzercode überspringt den Code bis zur nächsten Zeile des Benutzercodes.
  • Debuggen>Rücksprung (oder UMSCHALT+F11) in Nichtbenutzercode springt zurück zur nächsten Zeile des Benutzercodes.

Wenn kein Benutzercode mehr vorhanden ist, wird das Debuggen bis zum Ende fortgesetzt, es wird ein weiterer Haltepunkt erreicht oder ein Fehler ausgelöst.

Wenn der Debugger Nichtbenutzercode unterbricht (z. B., wenn Sie Debuggen>Alle unterbrechen verwenden und Nichtbenutzercode anhalten), wird das Fenster Keine Quelle angezeigt. Sie können dann über den Befehl Debuggen>Schritt zur nächsten Zeile des Benutzercodes wechseln.

Wenn ein Ausnahmefehler im Nichtbenutzercode auftritt, unterbricht der Debugger an der Benutzercodezeile, in der die Ausnahme generiert wurde.

Wenn Ausnahmen (erste Chance) für die Ausnahme aktiviert sind, wird die aufrufende Benutzercodezeile im Quellcode grün hervorgehoben. Im Fenster Aufrufstapel wird ein mit Anmerkungen versehener Frame mit der Bezeichnung [Externer Code] angezeigt.

"Nur eigenen Code" in C++

Ab Visual Studio 2017, Version 15.8, wird „Nur eigenen Code“ für die Codeausführung unterstützt. Diese Funktion erfordert auch die Verwendung des Compilerschalters /JMC (Debuggen von „Nur eigenen Code“). Der Schalter ist in C++-Projekten standardmäßig aktiviert. Für das Fenster Aufrufliste und die Unterstützung der Aufrufliste in „Nur eigenen Code“ ist der /JMC-Schalter nicht erforderlich.

Für die Klassifizierung als Benutzercode muss die PDB für die Binärdatei, die den Benutzercode enthält, vom Debugger geladen werden (über das Fenster Module können Sie dies überprüfen).

Für das Verhalten von Aufrufstapeln, wie z. B. im Fenster Aufrufstapel, betrachtet „Nur eigenen Code“ in C++ nur diese Funktionen als Nichtbenutzercode:

  • Funktionen mit entfernten Quellinformationen in ihrer Symboldatei.
  • Funktionen, bei denen die Symboldateien angeben, dass keine Quelldatei vorhanden ist, die dem Stapelrahmen entspricht.
  • Funktionen, die in .natjmc-Dateien im Ordner %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers angegeben werden.

Für das Verhalten bei der Codeausführung betrachtet „Nur eigenen Code“ in C++ nur diese Funktionen als Nichtbenutzercode:

  • Funktionen, für die die entsprechende PDB-Datei nicht in den Debugger geladen wurde.
  • Funktionen, die in .natjmc-Dateien im Ordner %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers angegeben werden.

Hinweis

Für die Unterstützung von Codeschritten in „Nur eigenen Code“ muss C++-Code mit den MSVC-Compilern in Visual Studio 15.8 Vorschauversion 3 oder höher kompiliert werden, und der /JMC-Compilerschalter muss aktiviert sein (er ist standardmäßig aktiviert). Weitere Informationen finden Sie unter Anpassen des Verhaltens von C++-Aufrufstapel und -Codeschritten und in diesem Blogbeitrag. Für Code, der mit einem älteren Compiler kompiliert wurde, sind .natstepfilter-Dateien die einzige Möglichkeit, das Codeschrittverhalten unabhängig von „Nur eigenen Code“ anzupassen. Weitere Informationen finden Sie unter Anpassen C++-Schrittverhaltens unabhängig von den Einstellungen für „Nur eigenen Code“

Beim Debuggen in C++ wird IDE-generierter Code standardmäßig übersprungen. Beim Debuggen in C++ gilt:

  • Bei Debuggen>Einzelschritt (oder F11) in IDE-generiertem Code wird der Code bis zur nächsten Zeile des Benutzercodes übersprungen, wenn Einzelschritt in IDE-generiertem Code aufgerufen wird.
  • Debuggen>Rücksprung (oder UMSCHALT+F11) in IDE-generiertem Code wird bis zur nächsten Zeile des Benutzercodes (außerhalb des aktuellen Stapelrahmens) ausgeführt.

Wenn kein Benutzercode mehr vorhanden ist, wird das Debuggen bis zum Ende fortgesetzt, es wird ein weiterer Haltepunkt erreicht oder ein Fehler ausgelöst.

Wenn der Debugger den Nichtbenutzercode unterbricht (zum Beispiel, wenn Sie Debuggen>Alle unterbrechen verwenden und Nichtbenutzercode anhalten), wird die schrittweise Ausführung im Nichtbenutzercode weitergeführt.

Wenn der Debugger auf eine Ausnahme trifft, hält er bei der Ausnahme an, unabhängig davon, ob sie im Benutzer- oder Nichtbenutzercode auftritt. Die Optionen Vom Benutzercode unbehandelt im Dialogfeld Ausnahmeeinstellungen werden ignoriert.

Anpassen des Verhaltens von C++-Aufrufsstapel und -Codeschritten

Für C++-Projekte können Sie die Module, Quelldateien und Funktionen angeben, die das Fenster Aufrufstapel als Nichtbenutzercode behandelt, indem Sie sie in .natjmc-Dateien festlegen. Diese Anpassung gilt auch für Codeschritte, wenn Sie den neuesten Compiler verwenden (siehe „Nur eigenen Code“ in C++).

  • Fügen Sie dem Ordner %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers die NATJMC-Datei hinzu, um Nichtbenutzercode aller Benutzer des Visual Studio-Computers anzugeben.
  • Fügen Sie die .natjmc-Datei zum Ordner %USERPROFILE%\Eigene Dokumente\<Visual Studio-Version>\Visualizers hinzu, um Nichtbenutzercode für einen einzelnen Benutzer anzugeben.

Eine .natjmc-Datei ist eine XML-Datei mit der folgenden Syntax:

<?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>

Modulelementattribute

Attribut BESCHREIBUNG
Name Erforderlich. Der vollständige Pfad des Moduls oder der Module. Sie können die Windows-Platzhalterzeichen ? (null oder ein Zeichen) und * (null oder mehr Zeichen) verwenden. Ein auf ein Objekt angewendeter

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

weist den Debugger an, alle Module in \3rdParty\UtilLibs auf einem Laufwerk als externen Code zu behandeln.
Company Dies ist optional. Der Name des Unternehmens, das das Modul veröffentlicht, das in die ausführbare Datei eingebettet ist. Sie können dieses Attribut verwenden, um die Module zu unterscheiden.

Dateielementattribute

Attribut BESCHREIBUNG
Name Erforderlich. Der vollständige Pfad der Quelldatei oder -dateien, die als externer Code behandelt werden sollen. Sie können die Windows-Platzhalterzeichen ? und * verwenden, wenn Sie den Pfad angeben.

Funktionselementattribute

Attribut BESCHREIBUNG
Name Erforderlich. Der vollqualifizierte Name der Funktion, die als externer Code behandelt werden soll. Sie können die Windows-Platzhalterzeichen ? und * verwenden, wenn Sie den Pfad angeben.
Module Optional. Der Name oder der vollständige Pfad zu dem Modul, das die Funktion enthält. Sie können dieses Attribut verwenden, um Funktionen mit demselben Namen zu unterscheiden.
ExceptionImplementation Bei Festlegung auf true zeigt die Aufrufliste die Funktion an, die die Ausnahme und nicht diese Funktion ausgelöst hat.

Anpassen C++-Schrittverhaltens unabhängig von den Einstellungen für „Nur eigenen Code“

In C++-Projekten können Sie Prozedurschrittfunktionen angeben, indem Sie sie als NoStepInto-Funktionen in NATSTEPFILTER-Dateien auflisten. Die in .natstepfilter-Dateien aufgeführten Funktionen sind nicht von Einstellungen für „Nur eigenen Code“ abhängig. Eine NoStepInto-Funktion weist den Debugger an, die Funktion auch dann zu überspringen, wenn einige StepInto-Funktionen oder anderer Benutzercode aufgerufen werden. Im Gegensatz zu Funktionen, die in .natjmc aufgeführt sind, wechselt der Debugger in die erste Zeile des Benutzercodes innerhalb der NoStepInto-Funktion und führt sie schrittweise aus.

  • Um Nichtbenutzercode für alle lokalen Visual Studio-Benutzer anzugeben, fügen Sie dem Ordner %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers die .natstepfilter-Datei hinzu.
  • Fügen Sie die .natstepfilter-Datei dem Ordner %USERPROFILE%\Eigene Dokumente\<Visual Studio-Version>\Visualizers hinzu, um Nichtbenutzercode für einen einzelnen Benutzer anzugeben.

Hinweis

Die .natstepfilter-Funktionalität ist in einigen Drittanbietererweiterungen möglicherweise deaktiviert.

Eine .natstepfilter-Datei ist eine XML-Datei mit der folgenden Syntax:

<?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>

Element BESCHREIBUNG
Function Erforderlich. Gibt eine oder mehreren Funktionen als Nichtbenutzerfunktionen an.
Name Erforderlich. Ein ECMA-262-formatierter regulärer Ausdruck, der den vollständigen Funktionsnamen angibt, der übereinstimmen muss. Zum Beispiel:

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

teilt dem Debugger mit, dass alle Methoden in MyNS::MyClass als Nichtbenutzercode behandelt werden sollen. Bei der Übereinstimmung muss die Groß-/Kleinschreibung beachtet werden.
Module Dies ist optional. Ein ECMA-262-formatierter regulärer Ausdruck, der den vollständigen Pfad zu dem Modul angibt, das die Funktion enthält. Die Groß- und Kleinschreibung wird bei der Übereinstimmung nicht berücksichtigt.
Action Erforderlich. Einer dieser Werte, bei denen die Groß-/Kleinschreibung beachtet werden muss.

NoStepInto – weist den Debugger an, die Funktion zu überspringen.
StepInto – weist den Debugger an, die Funktion schrittweise auszuführen, wobei alle anderen NoStepInto für die übereinstimmende Funktion überschrieben werden.

Weitere Informationen zu NATSTEPFILTER- und NATJMC-Dateien

  • Ab Visual Studio 2022, Version 17.6 können Sie .natjmc- und NATSTEPFILTER-Dateien direkt der Projektmappe oder dem Projekt hinzufügen.

  • Syntaxfehler in .natstepfilter- und .natjmc-Dateien werden im Ausgabefenster des Debuggers nicht gemeldet.

  • Im Gegensatz zu .natvis-Dateien, werden .natstepfilter- und .natjmc-Dateien nicht im laufenden Betrieb neu geladen. Stattdessen werden diese Dateien zu Beginn der Debugsitzung neu geladen.

  • Bei Vorlagenfunktionen kann die Verwendung von &lt;.*&gt; oder &lt;.* im Namen hilfreich sein.

"Nur eigenen Code" in JavaScript

„Nur eigenen Code“ in JavaScript steuert die Einzelschrittausführung und die Aufruflistenanzeige durch Kategorisieren von Code in einer dieser Klassifizierungen:

Klassifizierung Beschreibung
MyCode Benutzercode, den Sie besitzen und steuern.
LibraryCode Nicht-Benutzercode aus Bibliotheken, die Sie regelmäßig verwenden und die für das ordnungsgemäße Funktionieren Ihrer Anwendung benötigt werden (z. B. jQuery).
UnrelatedCode Nichtbenutzercode in Ihrer Anwendung, den Sie nicht besitzen und auf den Ihre Anwendung nicht zurückgreift, um korrekt zu funktionieren. Beispielsweise könnte ein SDK für Werbung, das Anzeigen anzeigt, UnrelatedCode sein.

Der JavaScript-Debugger klassifiziert Code als Benutzer- oder Nichtbenutzercode in dieser Reihenfolge:

  1. Die Standardklassifizierungen.

    • Skript, das ausgeführt wird, indem eine Zeichenfolge an die vom Host bereitgestellte eval-Funktion übergeben wird, lautet MyCode.
    • Skript, das ausgeführt wird, indem eine Zeichenfolge an den Function-Konstruktor übergeben wird, lautet LibraryCode.
    • Skript, das in einem Frameworkverweis, wie etwa WinJS oder dem Azure SDK, enthalten ist, wird als LibraryCode klassifiziert.
    • Skript, das ausgeführt wird, indem eine Zeichenfolge an die Funktionen setTimeout, setImmediate oder setInterval übergeben wird, ist UnrelatedCode.
  2. Klassifizierungen in der mycode.json-Datei des aktuellen Projekts.

Jeder Klassifizierungsschritt überschreibt die vorherigen Schritte.

Der restliche Code wird als MyCode klassifiziert.

Sie können die Standardklassifizierungen ändern und bestimmte Dateien und URLs als Benutzer- oder Nichtbenutzercode klassifizieren, indem Sie eine .json-Datei namens mycode.json zum Stammordner eines JavaScript-Projekts hinzufügen. Weitere Informationen finden Sie unter Anpassen von „Nur eigenen Code“ in JavaScript.

Beim JavaScript-Debuggen:

  • Wenn es sich bei einer Funktion um Nichtbenutzercode handelt, entspricht das Verhalten von Debuggen>Einzelschritt (oder F11) dem Verhalten von Debuggen>Rücksprung (oder F10).
  • Wenn ein Schritt im Nichtbenutzercode (LibraryCode oder UnrelatedCode) beginnt, dann verhält sich die schrittweise Ausführung kurzfristig so, als wäre „Nur eigenen Code“ nicht aktiviert. Sobald Sie zurück zum Benutzercode wechseln, wird die schrittweise Ausführung für „Nur eigenen Code“ erneut aktiviert.
  • Wenn ein Benutzercodeschritt dazu führt, dass der aktuelle Ausführungskontext verlassen wird, hält der Debugger bei der nächsten ausgeführten Benutzercodezeile an. Wenn beispielsweise ein Rückruf in LibraryCode-Code ausgeführt wird, fährt der Debugger fort, bis die nächste Zeile des Benutzercodes ausgeführt wird.
  • Rücksprung (oder UMSCHALT+F11) hält in der nächsten Zeile des Benutzercodes an.

Wenn kein Benutzercode mehr vorhanden ist, wird das Debuggen bis zum Ende fortgesetzt, es wird ein weiterer Haltepunkt erreicht oder ein Fehler ausgelöst.

Im Code gesetzte Haltepunkte werden immer getroffen, jedoch ist der Code klassifiziert.

  • Wenn das debugger-Schlüsselwort in LibraryCode vorkommt, unterbricht der Debugger immer die Ausführung.
  • Wenn das debugger-Schlüsselwort in UnrelatedCode vorkommt, stoppt der Debugger nicht.

Wenn eine nicht behandelte Ausnahme in MyCode oder LibraryCode-Code auftritt, unterbricht der Debugger immer die Ausführung.

Wenn eine nicht behandelte Ausnahme in UnrelatedCode auftritt und sich MyCode oder LibraryCode im Aufrufstapel befindet, unterbricht der Debugger die Ausführung.

Wenn Ausnahmen (erste Chance) für die Ausnahme aktiviert sind und die Ausnahme in LibraryCode oder UnrelatedCode ausgelöst wird:

  • Wenn die Ausnahme behandelt wird, unterbricht der Debugger nicht.
  • Wenn die Ausnahme nicht behandelt wird, unterbricht der Debugger.

Anpassen von „Nur eigenen Code“ in JavaScript

Um Benutzer- und Nichtbenutzercode für ein einzelnes JavaScript-Projekt zu kategorisieren, können Sie dem Stammordner des Projekts eine .json-Datei mit dem Namen mycode.json hinzufügen.

Die mycode.json-Datei muss nicht alle Schlüssel-Wert-Paare auflisten. Die Werte MyCode, Libraries und Unrelated können leere Arrays sein.

Mycode.json-Dateien verwenden folgende Syntax:

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

Eval, Function und ScriptBlock

Die Schlüsselwertpaare Eval, Function und ScriptBlock bestimmen, wie dynamisch erzeugter Code klassifiziert wird:

name Beschreibung
Eval Skript, das ausgeführt wird, indem eine Zeichenfolge an die vom Host bereitgestellte eval-Funktion übergeben wird. Standardmäßig wird ein Eval-Skript als MyCode klassifiziert.
Function Skript, das ausgeführt wird, indem eine Zeichenfolge an den Function-Konstruktor übergeben wird. Standardmäßig wird ein Function-Skript als LibraryCode klassifiziert.
ScriptBlock Skript, das ausgeführt wird, indem eine Zeichenfolge an die Funktionen setTimeout, setImmediate oder setInterval übergeben wird. Standardmäßig wird ein ScriptBlock-Skript als UnrelatedCode klassifiziert.

Sie können den Wert auf eines dieser Schlüsselwörter ändern:

  • MyCode klassifiziert das Skript als MyCode.
  • Library klassifiziert das Skript als LibraryCode.
  • Unrelated klassifiziert das Skript als UnrelatedCode.

MyCode, Libraries und Unrelated

Die Schlüsselwertpaare MyCode, Libraries und Unrelated geben die URLs oder Dateien an, die Sie in eine Klassifikation einschließen möchten:

name Beschreibung
MyCode Ein Array von URLs oder Dateien, die als MyCode klassifiziert werden.
Libraries Ein Array von URLs oder Dateien, die als LibraryCode klassifiziert werden.
Unrelated Ein Array von URLs oder Dateien, die als UnrelatedCode klassifiziert werden.

Die URL-Zeichenfolge oder Dateizeichenfolge kann eine oder mehrere *-Zeichen enthalten, die mit null oder mehr Zeichen übereinstimmen. * entspricht dem regulären Ausdruck .*.