Freigeben über


Debuggerskripts mit JavaScript

In diesem Thema wird beschrieben, wie Sie JavaScript zum Erstellen von Skripts verwenden, die Debuggerobjekte verstehen und die Funktionen des Debuggers erweitern und anpassen.

Übersicht über javaScript-Debuggerskripting

Skriptanbieter verbinden eine Skriptsprache mit dem internen Objektmodell des Debuggers. Der JavaScript-Debuggerskriptinganbieter ermöglicht die Verwendung von JavaScript mit dem Debugger.

Wenn ein JavaScript über den .scriptload-Befehl geladen wird, wird der Hauptcode des Skripts ausgeführt, die Namen, die im Skript enthalten sind, in den Stammnamensraum des Debuggers (dx Debugger) eingebunden, und das Skript bleibt im Speicher, bis es entladen wird und alle Verweise auf seine Objekte freigegeben werden. Das Skript kann dem Ausdrucksauswerter des Debuggers neue Funktionen bereitstellen, das Objektmodell des Debuggers ändern oder auf ähnliche Weise wie eine NatVis-Visualisierung fungieren.

In diesem Thema wird beschrieben, was Sie mit javaScript-Debuggerskripting tun können.

Diese beiden Themen enthalten zusätzliche Informationen zum Arbeiten mit JavaScript im Debugger.

JavaScript-Debuggerbeispielskripts

Native Objekte in JavaScript-Erweiterungen

JavaScript-Script-Video

Defrag Tools #170 – Andy und Bill veranschaulichen die JavaScript-Erweiterbarkeit und Skriptfunktionen im Debugger.

Der Debugger-JavaScript-Anbieter

Der im Debugger enthaltene JavaScript-Anbieter nutzt die neuesten ECMAScript6-Objekt- und Klassenverbesserungen. Weitere Informationen finden Sie unter ECMAScript 6 – Neue Features: Übersicht & Vergleich.

JsProvider.dll

JsProvider.dll ist der JavaScript-Anbieter, der geladen wird, um JavaScript Debugger Scripting zu unterstützen.

Anforderungen

JavaScript-Debuggerskripting ist für die Arbeit mit allen unterstützten Versionen von Windows konzipiert.

Laden des JavaScript-Skriptinganbieters

Bevor Sie einen der Skriptbefehle verwenden, muss ein Skriptanbieter geladen werden. Verwenden Sie den Befehl ".scriptproviders", um zu bestätigen, dass der JavaScript-Anbieter geladen wurde.

0:000> .scriptproviders
Available Script Providers:
    NatVis (extension '.NatVis')
    JavaScript (extension '.js')

JavaScript-Skripting-Metabefehle

Die folgenden Befehle stehen für die Verwendung von JavaScript-Debuggerskripting zur Verfügung.

Anforderungen

Bevor Sie einen der Skriptbefehle verwenden, muss ein Skriptanbieter geladen werden. Verwenden Sie den Befehl ".scriptproviders", um zu bestätigen, dass der JavaScript-Anbieter geladen wurde.

0:000> .scriptproviders
Available Script Providers:
    NatVis (extension '.NatVis')
    JavaScript (extension '.js')

.skriptanbieter (Liste von Skriptanbietern)

Der Befehl ".scriptproviders" listet alle Skriptsprachen auf, die derzeit vom Debugger und der Erweiterung verstanden werden, unter der sie registriert sind.

Im folgenden Beispiel werden die JavaScript- und NatVis-Anbieter geladen.

0:000> .scriptproviders
Available Script Providers:
    NatVis (extension '.NatVis')
    JavaScript (extension '.js')

Jede Datei, die mit ".NatVis" endet, wird als NatVis-Skript verstanden, und jede Datei, die mit ".js" endet, wird als JavaScript-Skript verstanden. Jeder Skripttyp kann mit dem Befehl ".scriptload" geladen werden.

Weitere Informationen finden Sie unter .scriptproviders (List Script Providers)

.scriptload (Skript laden)

Der Befehl ".scriptload" lädt ein Skript und führt den Stammcode eines Skripts und die InitializeScript-Funktion aus. Wenn beim anfänglichen Laden und Ausführen des Skripts Fehler auftreten, werden die Fehler in der Konsole angezeigt. Der folgende Befehl zeigt das erfolgreiche Laden von TestScript.js.

0:000> .scriptload C:\WinDbg\Scripts\TestScript.js
JavaScript script successfully loaded from 'C:\WinDbg\Scripts\TestScript.js'

Alle Vom Skript vorgenommenen Objektmodellmanipulationen bleiben erhalten, bis das Skript anschließend entladen oder erneut mit unterschiedlichem Inhalt ausgeführt wird.

Weitere Informationen finden Sie unter .scriptload (Load Script)

.scriptrun

Der Befehl ".scriptrun" lädt ein Skript, führt den Stammcode des Skripts, das InitializeScript und die InvokeScript-Funktion aus. Wenn beim anfänglichen Laden und Ausführen des Skripts Fehler auftreten, werden die Fehler in der Konsole angezeigt.

0:000> .scriptrun C:\WinDbg\Scripts\helloWorld.js
JavaScript script successfully loaded from 'C:\WinDbg\Scripts\helloWorld.js'
Hello World!  We are in JavaScript!

Alle Vom Skript vorgenommenen Debuggerobjektmodellmanipulationen bleiben erhalten, bis das Skript anschließend entladen oder erneut mit unterschiedlichem Inhalt ausgeführt wird.

Weitere Informationen finden Sie unter .scriptrun (Run Script).

.scriptunload (Skript entladen)

Der Befehl ".scriptunload" entlädt ein geladenes Skript und ruft die UninitializeScript-Funktion auf. Verwenden der folgenden Befehlssyntax zum Entladen eines Skripts

0:000:x86> .scriptunload C:\WinDbg\Scripts\TestScript.js
JavaScript script unloaded from 'C:\WinDbg\Scripts\TestScript.js'

Weitere Informationen finden Sie unter .scriptunload (Unload Script).

.scriptlist (Liste geladener Skripts)

Der Befehl ".scriptlist" listet alle Skripts auf, die über das SKRIPTload oder den .scriptrun-Befehl geladen wurden. Wenn testScript erfolgreich mit .scriptload geladen wurde, zeigt der Befehl ".scriptlist" den Namen des geladenen Skripts an.

0:000> .scriptlist
Command Loaded Scripts:
    JavaScript script from 'C:\WinDbg\Scripts\TestScript.js'

Weitere Informationen finden Sie unter ".scriptlist" (Liste geladener Skripts).For more information, see .scriptlist (List Loaded Scripts).

Erste Schritte mit JavaScript-Debuggerskripting

HelloWorld-Beispielskript

In diesem Abschnitt wird beschrieben, wie Sie ein einfaches JavaScript-Debuggerskript erstellen und ausführen, das ausdruckt, Hello World.

// WinDbg JavaScript sample
// Prints Hello World
function initializeScript()
{
    host.diagnostics.debugLog("***> Hello World! \n");
}

Verwenden Sie einen Text-Editor wie Editor, um eine Textdatei namens HelloWorld.js zu erstellen, die den oben gezeigten JavaScript-Code enthält.

Verwenden Sie den Befehl ".scriptload", um das Skript zu laden und auszuführen. Da wir den Funktionsnamen initializeScript verwendet haben, wird der Code in der Funktion ausgeführt, wenn das Skript geladen wird.

0:000> .scriptload c:\WinDbg\Scripts\HelloWorld.js
JavaScript script successfully loaded from 'c:\WinDbg\Scripts\HelloWorld.js'
***> Hello World! 

Nachdem das Skript geladen wurde, ist die zusätzliche Funktionalität im Debugger verfügbar. Verwenden Sie den Dx-Befehl (NatVis-Ausdruck anzeigen), um Debugger.State.Scripts anzuzeigen, um zu sehen, dass unser Skript jetzt vorhanden ist.

0:000> dx Debugger.State.Scripts
Debugger.State.Scripts                
    HelloWorld 

Im nächsten Beispiel fügen wir eine benannte Funktion hinzu und rufen sie auf.

Hinzufügen von zwei Werten (Beispielskript)

In diesem Abschnitt wird beschrieben, wie Sie ein einfaches JavaScript-Debuggerskript erstellen und ausführen, das Eingaben hinzufügt und zwei Zahlen hinzufügt.

Dieses einfache Skript bietet eine einzelne Funktion, addTwoValues.

// WinDbg JavaScript sample
// Adds two functions
function addTwoValues(a, b)
 {
     return a + b;
 }

Verwenden Sie einen Text-Editor wie Notepad, um eine Textdatei mit dem Namen FirstSampleFunction.js zu erstellen.

Verwenden Sie den Befehl ".scriptload", um das Skript zu laden.

0:000> .scriptload c:\WinDbg\Scripts\FirstSampleFunction.js
JavaScript script successfully loaded from 'c:\WinDbg\Scripts\FirstSampleFunction.js'

Nachdem das Skript geladen wurde, ist die zusätzliche Funktionalität im Debugger verfügbar. Verwenden Sie den Dx-Befehl (NatVis-Ausdruck anzeigen), um Debugger.State.Scripts anzuzeigen, um zu sehen, dass unser Skript jetzt vorhanden ist.

0:000> dx Debugger.State.Scripts
Debugger.State.Scripts                
    FirstSampleFunction    

Wir können die FirstSampleFunction auswählen, um zu sehen, welche Funktionen sie bereitstellt.

0:000> dx -r1 -v Debugger.State.Scripts.FirstSampleFunction.Contents
Debugger.State.Scripts.FirstSampleFunction.Contents                 : [object Object]
    host             : [object Object]
    addTwoValues    
 ... 

Um das Arbeiten mit dem Skript etwas bequemer zu gestalten, weisen Sie im Debugger eine Variable zu, die den Inhalt des Skripts mithilfe des dx-Befehls speichert.

0:000> dx @$myScript = Debugger.State.Scripts.FirstSampleFunction.Contents

Verwenden Sie den Dx-Ausdrucks-Evaluator, um die addTwoValues-Funktion aufzurufen.

0:000> dx @$myScript.addTwoValues(10, 41),d
@$myScript.addTwoValues(10, 41),d : 51

Sie können auch die @ $scriptContents integrierten Alias verwenden, um mit den Skripts zu arbeiten. Der @$scriptContents-Alias kombiniert den Inhalt aller geladenen Skripte.

0:001> dx @$scriptContents.addTwoValues(10, 40),d
@$scriptContents.addTwoValues(10, 40),d : 50

Wenn Sie mit dem Skript fertig sind, verwenden Sie den Befehl ".scriptunload" zum Entladen des Skripts.

0:000> .scriptunload c:\WinDbg\Scripts\FirstSampleFunction.js
JavaScript script successfully unloaded from 'c:\WinDbg\Scripts\FirstSampleFunction.js'

Debuggerbefehlsautomatisierung

In diesem Abschnitt wird beschrieben, wie Sie ein einfaches JavaScript-Debuggerskript erstellen und ausführen, das das Senden des Befehls "u" (Unassemble) automatisiert. Im Beispiel wird auch gezeigt, wie Befehlsausgabe in einer Schleife erfasst und angezeigt wird.

Dieses Skript stellt eine einzelne Funktion bereit, RunCommands().

// WinDbg JavaScript sample
// Shows how to call a debugger command and display results
"use strict";

function RunCommands()
{
var ctl = host.namespace.Debugger.Utility.Control;   
var output = ctl.ExecuteCommand("u");
host.diagnostics.debugLog("***> Displaying command output \n");

for (var line of output)
   {
   host.diagnostics.debugLog("  ", line, "\n");
   }

host.diagnostics.debugLog("***> Exiting RunCommands Function \n");

}

Verwenden Sie einen Text-Editor wie Editor, um eine Textdatei mit dem Namen RunCommands.js zu erstellen.

Verwenden Sie den Befehl ".scriptload", um das RunCommands-Skript zu laden.

0:000> .scriptload c:\WinDbg\Scripts\RunCommands.js 
JavaScript script successfully loaded from 'c:\WinDbg\Scripts\RunCommands.js'

Nachdem das Skript geladen wurde, ist die zusätzliche Funktionalität im Debugger verfügbar. Verwenden Sie den Dx-Befehl (NatVis-Ausdruck anzeigen), um Debugger.State.Scripts.RunCommands anzuzeigen, um zu sehen, dass unser Skript jetzt ansässig ist.

0:000>dx -r3 Debugger.State.Scripts.RunCommands
Debugger.State.Scripts.RunCommands                
    Contents         : [object Object]
        host             : [object Object]
            diagnostics      : [object Object]
            namespace       
            currentSession   : Live user mode: <Local>
            currentProcess   : notepad.exe
            currentThread    : ntdll!DbgUiRemoteBreakin (00007ffd`87f2f440) 
            memory           : [object Object]

Verwenden Sie den Dx-Befehl, um die RunCommands-Funktion im RunCommands-Skript aufzurufen.

0:000> dx Debugger.State.Scripts.RunCommands.Contents.RunCommands()
  ***> Displaying command output
  ntdll!ExpInterlockedPopEntrySListEnd+0x17 [d:\rs1\minkernel\ntos\rtl\amd64\slist.asm @ 196]:
  00007ffd`87f06e67 cc              int     3
  00007ffd`87f06e68 cc              int     3
  00007ffd`87f06e69 0f1f8000000000  nop     dword ptr [rax]
  ntdll!RtlpInterlockedPushEntrySList [d:\rs1\minkernel\ntos\rtl\amd64\slist.asm @ 229]:
  00007ffd`87f06e70 0f0d09          prefetchw [rcx]
  00007ffd`87f06e73 53              push    rbx
  00007ffd`87f06e74 4c8bd1          mov     r10,rcx
  00007ffd`87f06e77 488bca          mov     rcx,rdx
  00007ffd`87f06e7a 4c8bda          mov     r11,rdx
***> Exiting RunCommands Function

Spezielle JavaScript-Debuggerfunktionen

Es gibt mehrere spezielle Funktionen in einem JavaScript-Skript, das vom Skriptanbieter selbst aufgerufen wird.

SkriptInitialisieren

Wenn ein JavaScript-Skript geladen und ausgeführt wird, durchläuft es eine Reihe von Schritten, bevor sich die Variablen, Funktionen und andere Objekte im Skript auf das Objektmodell des Debuggers auswirken.

  • Das Skript wird in den Arbeitsspeicher geladen und analysiert.
  • Der Stammcode im Skript wird ausgeführt.
  • Wenn das Skript über eine Methode mit dem Namen InitializeScript verfügt, wird diese Methode aufgerufen.
  • Der Rückgabewert aus initializeScript wird verwendet, um zu bestimmen, wie das Objektmodell des Debuggers automatisch geändert wird.
  • Die Namen im Skript werden in den Namespace des Debuggers eingebunden.

Wie bereits erwähnt, wird InitializeScript unmittelbar aufgerufen, nachdem der Stammcode des Skripts ausgeführt wurde. Der Auftrag besteht darin, ein JavaScript-Array von Registrierungsobjekten an den Anbieter zurückzugeben, der angibt, wie das Objektmodell des Debuggers geändert wird.

function initializeScript()
{
    // Add code here that you want to run every time the script is loaded. 
    // We will just send a message to indicate that function was called.
    host.diagnostics.debugLog("***> initializeScript was called\n");
}

invokeScript

Die invokeScript-Methode ist die primäre Skriptmethode und wird aufgerufen, wenn .scriptload und .scriptrun ausgeführt werden.

function invokeScript()
{
    // Add code here that you want to run every time the script is executed. 
    // We will just send a message to indicate that function was called.
    host.diagnostics.debugLog("***> invokeScript was called\n");
}

uninitializeScript

Die uninitializeScript-Methode ist das Verhaltens-Gegenteil der initializeScript-Methode. Es wird aufgerufen, wenn eine Verknüpfung eines Skripts aufgehoben wird und bereit zum Entladen ist. Der Auftrag besteht darin, alle Änderungen am Objektmodell rückgängig zu machen, die das Skript während der Ausführung zwingend vorgenommen hat, und/oder alle Objekte zu zerstören, die das Skript zwischengespeichert hat.

Wenn ein Skript weder imperative Manipulationen an das Objektmodell vornimmt noch Ergebnisse zwischenspeichert, muss keine nicht initializeScript-Methode vorhanden sein. Alle Änderungen am Objektmodell, die durch den Rückgabewert von initializeScript angegeben werden, werden automatisch vom Anbieter rückgängig gemacht. Für solche Änderungen ist keine explizite uninitializeScript-Methode erforderlich.

function uninitializeScript()
{
    // Add code here that you want to run every time the script is unloaded. 
    // We will just send a message to indicate that function was called.
    host.diagnostics.debugLog("***> uninitialize was called\n");
}

Zusammenfassung der von Skriptbefehlen aufgerufenen Funktionen

In dieser Tabelle wird zusammengefasst, welche Funktionen von den Skriptbefehlen aufgerufen werden.

Befehl .scriptload .scriptrun (Run Script) .scriptunload (Unload Script)
wurzel ja ja
initializeScript ja ja
invokeScript ja
uninitializeScript ja

Verwenden Sie diesen Beispielcode, um zu sehen, wann jede Funktion aufgerufen wird, während das Skript geladen, ausgeführt und entladen wird.

// Root of Script
host.diagnostics.debugLog("***>; Code at the very top (root) of the script is always run \n");


function initializeScript()
{
    // Add code here that you want to run every time the script is loaded. 
    // We will just send a message to indicate that function was called.
    host.diagnostics.debugLog("***>; initializeScript was called \n");
}

function invokeScript()
{
    // Add code here that you want to run every time the script is executed. 
    // We will just send a message to indicate that function was called.
    host.diagnostics.debugLog("***>; invokeScript was called \n");
}


function uninitializeScript()
{
    // Add code here that you want to run every time the script is unloaded. 
    // We will just send a message to indicate that function was called.
    host.diagnostics.debugLog("***>; uninitialize was called\n");
}


function main()
{
    // main is just another function name in JavaScript
    // main is not called by .scriptload or .scriptrun  
    host.diagnostics.debugLog("***>; main was called \n");
}

Erstellen eines Debugger-Visualizers in JavaScript

Mit benutzerdefinierten Visualisierungsdateien können Sie Daten in einer Visualisierungsstruktur gruppieren und organisieren, die die Datenbeziehungen und Inhalte besser widerspiegelt. Sie können die JavaScript-Debuggererweiterungen verwenden, um Debuggerschnellansichten zu schreiben, die ähnlich wie NatVis funktionieren. Dies erfolgt über die Erstellung eines JavaScript-Prototypobjekts (oder einer ES6-Klasse), das als Visualizer für einen bestimmten Datentyp fungiert. Weitere Informationen zu NatVis und dem Debugger finden Sie unter dx (Display NatVis Expression).For more information about NatVis and the debugger see dx (Display NatVis Expression).

Beispielklasse – Simple1DArray

Betrachten Sie ein Beispiel für eine C++-Klasse, die ein eindimensionales Array darstellt. Diese Klasse verfügt über zwei Member: m_size, die Gesamtgröße des Arrays, und m_pValues, ein Zeiger auf eine Anzahl von Ganzzahlen im Arbeitsspeicher, die dem Feld m_size entsprechen.

class Simple1DArray
{
private:

    ULONG64 m_size;
    int *m_pValues;
};

Wir können den Dx-Befehl verwenden, um das Standardmäßige Datenstrukturrendering zu betrachten.

0:000> dx g_array1D
g_array1D                 [Type: Simple1DArray]
    [+0x000] m_size           : 0x5 [Type: unsigned __int64]
    [+0x008] m_pValues        : 0x8be32449e0 : 0 [Type: int *]

JavaScript Visualizer

Um diesen Typ zu visualisieren, müssen wir eine Prototypklasse (oder ES6) erstellen, die alle Felder und Eigenschaften enthält, die der Debugger anzeigen soll. Außerdem muss die initializeScript-Methode ein Objekt zurückgeben, das dem JavaScript-Anbieter angibt, unseren Prototyp als Visualizer für den angegebenen Typ zu verknüpfen.

function initializeScript()
{
    //
    // Define a visualizer class for the object.
    //
    class myVisualizer
    {
        //
        // Create an ES6 generator function which yields back all the values in the array.
        //
        *[Symbol.iterator]()
        {
            var size = this.m_size;
            var ptr = this.m_pValues;
            for (var i = 0; i < size; ++i)
            {
                yield ptr.dereference();

                //
                // Note that the .add(1) method here is effectively doing pointer arithmetic on
                // the underlying pointer.  It is moving forward by the size of 1 object.
                //
                ptr = ptr.add(1);
            }
        }
    }

    return [new host.typeSignatureRegistration(myVisualizer, "Simple1DArray")];
}

Speichern Sie das Skript in einer Datei mit dem Namen arrayVisualizer.js.

Verwenden Sie den Befehl .load (Load Extension DLL), um den JavaScript-Anbieter zu laden.

0:000> .load C:\ScriptProviders\jsprovider.dll

Verwenden Sie .scriptload, um das Array-Visualizer-Skript zu laden.

0:000> .scriptload c:\WinDbg\Scripts\arrayVisualizer.js
JavaScript script successfully loaded from 'c:\WinDbg\Scripts\arrayVisualizer.js'

Wenn nun der Dx-Befehl verwendet wird, wird der Skriptvisualisierer Zeilen der Arrayinhalte darstellen.

0:000> dx g_array1D
g_array1D                 : [object Object] [Type: Simple1DArray]
    [<Raw View>]     [Type: Simple1DArray]
    [0x0]            : 0x0
    [0x1]            : 0x1
    [0x2]            : 0x2
    [0x3]            : 0x3
    [0x4]            : 0x4

Darüber hinaus stellt diese JavaScript-Visualisierung LINQ-Funktionen bereit, z. B. Select.

0:000> dx g_array1D.Select(n => n * 3),d
g_array1D.Select(n => n * 3),d                
    [0]              : 0
    [1]              : 3
    [2]              : 6
    [3]              : 9
    [4]              : 12

Auswirkungen auf die Visualisierung

Ein Prototyp oder eine Klasse, der die Visualisierung für einen systemeigenen Typ über eine Rückgabe eines host.typeSignatureRegistration-Objekts aus initializeScript erstellt, verfügt über alle Eigenschaften und Methoden innerhalb von JavaScript, die dem nativen Typ hinzugefügt werden. Darüber hinaus gelten die folgenden Semantiken:

  • Jeder Name, der nicht mit zwei Unterstrichen (__) beginnt, ist in der Visualisierung verfügbar.

  • Namen, die Teil von Standard-JavaScript-Objekten sind oder Teil von Protokollen sind, die vom JavaScript-Anbieter erstellt werden, werden in der Visualisierung nicht angezeigt.

  • Ein Objekt kann über die Unterstützung von [Symbol.iterator] iterierbar gemacht werden.

  • Ein Objekt kann über die Unterstützung eines benutzerdefinierten Protokolls indiziert werden, das aus mehreren Funktionen besteht: getDimensionality, getValueAt und optional setValueAt.

Native und JavaScript-Objektbrücke

Die Brücke zwischen JavaScript und dem Objektmodell des Debuggers ist bidirektional. Systemeigene Objekte können an JavaScript übergeben werden, und JavaScript-Objekte können an den Ausdrucksauswerter des Debuggers übergeben werden. Betrachten Sie als Beispiel die Hinzufügung der folgenden Methode in unserem Skript:

function multiplyBySeven(val)
{
    return val * 7;
}

Diese Methode kann jetzt in der obigen LINQ-Beispielabfrage verwendet werden. Zuerst laden wir die JavaScript-Visualisierung.

0:000> .scriptload c:\WinDbg\Scripts\arrayVisualizer2.js
JavaScript script successfully loaded from 'c:\WinDbg\Scripts\arrayVisualizer2.js'

0:000> dx @$myScript = Debugger.State.Scripts.arrayVisualizer2.Contents

Dann können wir die multiplyBySeven-Funktion inline verwenden, wie unten dargestellt.

0:000> dx g_array1D.Select(@$myScript.multiplyBySeven),d
g_array1D.Select(@$myScript.multiplyBySeven),d                
    [0]              : 0
    [1]              : 7
    [2]              : 14
    [3]              : 21
    [4]              : 28

Bedingte Haltepunkte mit JavaScript

Sie können JavaScript verwenden, um eine zusätzliche Verarbeitung durchzuführen, nachdem ein Haltepunkt erreicht wurde. Beispielsweise kann ein Skript verwendet werden, um andere Laufzeitwerte zu untersuchen und dann festzustellen, ob Sie die Codeausführung automatisch fortsetzen oder beenden möchten, und zusätzliches manuelles Debuggen ausführen möchten.

Allgemeine Informationen zum Arbeiten mit Haltepunkten finden Sie unter Methoden zum Steuern von Haltepunkten.

DebugHandler.js Beispielskript für die Haltepunktverarbeitung

In diesem Beispiel wird das Öffnen- und Speichern-Dialogfenster von Notepad ausgewertet: notepad!ShowOpenSaveDialog. Dieses Skript wertet die pszCaption-Variable aus, um zu ermitteln, ob das aktuelle Dialogfeld ein Dialogfeld "Öffnen" ist oder ob es sich um ein Dialogfeld "Speichern unter" handelt. Wenn es sich um ein geöffnetes Dialogfeld handelt, wird die Codeausführung fortgesetzt. Wenn es sich um ein "Speichern unter"-Dialog handelt, wird die Programmausführung gestoppt, und der Debugger hält an.

 // Use JavaScript strict mode 
"use strict";

// Define the invokeScript method to handle breakpoints

 function invokeScript()
 {
    var ctl = host.namespace.Debugger.Utility.Control;

    //Get the address of my string
    var address = host.evaluateExpression("pszCaption");

    // The open and save dialogs use the same function
    // When we hit the open dialog, continue.
    // When we hit the save dialog, break.
    if (host.memory.readWideString(address) == "Open") {
        // host.diagnostics.debugLog("We're opening, let's continue!\n");
        ctl.ExecuteCommand("gc");
    }
    else
    {
        //host.diagnostics.debugLog("We're saving, let's break!\n");
    }
  }

Mit diesem Befehl wird ein Haltepunkt bei notepad!ShowOpenSaveDialog festgelegt und das obige Skript wird jedes Mal ausgeführt, wenn dieser Haltepunkt erreicht wird.

bp notepad!ShowOpenSaveDialog ".scriptrun C:\\WinDbg\\Scripts\\DebugHandler.js"

Wenn dann die Option "Datei > speichern" im Editor ausgewählt ist, wird das Skript ausgeführt, der Befehl g nicht gesendet, und eine Unterbrechung der Codeausführung tritt auf.

JavaScript script successfully loaded from 'C:\WinDbg\Scripts\DebugHandler.js'
notepad!ShowOpenSaveDialog:
00007ff6`f9761884 48895c2408      mov     qword ptr [rsp+8],rbx ss:000000db`d2a9f2f0=0000021985fe2060

Arbeiten mit 64-Bit-Werten in JavaScript-Erweiterungen

In diesem Abschnitt wird beschrieben, wie sich 64-Bit-Werte, die in eine JavaScript-Debuggererweiterung übergeben werden, verhalten. Dieses Problem tritt auf, da JavaScript nur die Möglichkeit hat, Zahlen mit 53-Bits zu speichern.

64-Bit- und JavaScript-53-Bit-Speicher

Ordinalwerte, die in JavaScript übergeben werden, werden normalerweise als JavaScript-Zahlen geparsed. Das Problem besteht darin, dass JavaScript-Zahlen 64-Bit-Gleitkommawerte mit doppelter Genauigkeit sind. Alle Ordinalzahlen über 53 Bit verlieren ihre Genauigkeit beim Übertragen an JavaScript. Dies stellt ein Problem für 64-Bit-Zeiger und andere 64-Bit-Ordinalwerte dar, die Flags in den höchsten Bytes aufweisen können. Um dies zu bewältigen, wird jeder 64-Bit-native Wert (ob aus systemeigenem Code oder dem Datenmodell), der in JavaScript eingeht, als Bibliothekstyp und nicht als JavaScript-Zahl dargestellt. Dieser Bibliothekstyp wird zurück zum systemeigenen Code zurückwechseln, ohne dass die numerische Genauigkeit verloren geht.

Automatische Konvertierung

Der Bibliothekstyp für 64-Bit-Ordinalwerte unterstützt die Standardmäßige JavaScript-WertOf-Konvertierung. Wenn das Objekt in einem mathematischen Vorgang oder einem anderen Konstrukt verwendet wird, das eine Wertkonvertierung erfordert, wird es automatisch in eine JavaScript-Zahl konvertiert. Wenn ein Genauigkeitsverlust auftritt (der Wert verwendet mehr als 53-Bit-Ordnungsgenauigkeit), löst der JavaScript-Anbieter eine Ausnahme aus.

Beachten Sie, dass Sie bei Verwendung bitweiser Operatoren in JavaScript weiter auf 32-Bit-Genauigkeit beschränkt sind.

Dieser Beispielcode summiert zwei Zahlen und wird verwendet, um die Konvertierung von 64-Bit-Werten zu testen.

function playWith64BitValues(a64, b64)
{
    // Sum two numbers to demonstrate 64-bit behavior.
    //
    // Imagine a64==100, b64==1000
    // The below would result in sum==1100 as a JavaScript number.  No exception is thrown.  The values auto-convert.
    //
    // Imagine a64==2^56, b64=1
    // The below will **Throw an Exception**.  Conversion to numeric results in loss of precision!
    //
    var sum = a64 + b64;
    host.diagnostics.debugLog("Sum   >> ", sum, "\n");

}

function performOp64BitValues(a64, b64, op)
{
    //
    // Call a data model method passing 64-bit value.  There is no loss of precision here.  This round trips perfectly.
    // For example:
    //  0:000> dx @$myScript.playWith64BitValues(0x4444444444444444ull, 0x3333333333333333ull, (x, y) => x + y)
    //  @$myScript.playWith64BitValues(0x4444444444444444ull, 0x3333333333333333ull, (x, y) => x + y) : 0x7777777777777777
    //
    return op(a64, b64);
}

Verwenden Sie einen Text-Editor wie Editor, um eine Textdatei mit dem Namen PlayWith64BitValues.js zu erstellen.

Verwenden Sie den Befehl ".scriptload", um das Skript zu laden.

0:000> .scriptload c:\WinDbg\Scripts\PlayWith64BitValues.js
JavaScript script successfully loaded from 'c:\WinDbg\Scripts\PlayWith64BitValues.js'

Um das Arbeiten mit dem Skript etwas bequemer zu gestalten, weisen Sie im Debugger eine Variable zu, die den Inhalt des Skripts mithilfe des dx-Befehls speichert.

0:000> dx @$myScript = Debugger.State.Scripts.PlayWith64BitValues.Contents

Verwenden Sie den Dx-Ausdrucks-Evaluator, um die addTwoValues-Funktion aufzurufen.

Zunächst berechnen wir den Wert 2^53 =9007199254740992 (Hex 0x20000000000000).

Zunächst werden wir (2^53) - 2 verwenden und sehen, dass der richtige Wert für die Summe zurückgegeben wird.

0:000> dx @$myScript.playWith64BitValues(9007199254740990, 9007199254740990)
Sum   >> 18014398509481980

Anschließend berechnen wir (2^53) -1 =9007199254740991. Dadurch wird der Fehler zurückgegeben, der angibt, dass der Konvertierungsprozess die Genauigkeit verliert, sodass dies der größte Wert ist, der mit der Summenmethode im JavaScript-Code verwendet werden kann.

0:000> dx @$myScript.playWith64BitValues(9007199254740990, 9007199254740991)
Error: 64 bit value loses precision on conversion to number

Rufen Sie eine Datenmodellmethode auf, die 64-Bit-Werte übergibt. Hier gibt es keinen Genauigkeitsverlust.

0:001> dx @$myScript.performOp64BitValues( 0x7FFFFFFFFFFFFFFF,  0x7FFFFFFFFFFFFFFF, (x, y) => x + y)
@$myScript.performOp64BitValues( 0x7FFFFFFFFFFFFFFF,  0x7FFFFFFFFFFFFFFF, (x, y) => x + y) : 0xfffffffffffffffe

Vergleich

Der 64-Bit-Bibliothekstyp ist ein JavaScript-Objekt und kein Werttyp wie eine JavaScript-Nummer. Dies hat einige Auswirkungen auf Vergleichsvorgänge. Normalerweise würde die Gleichheit (==) eines Objekts darauf hinweisen, dass Operanden auf dasselbe Objekt und nicht auf denselben Wert verweisen. Der JavaScript-Provider mindert das, indem er Live-Referenzen auf 64-Bit-Werte nachverfolgt und dasselbe "unveränderliche" Objekt für nicht eingesammelte 64-Bit-Werte zurückgibt. Dies bedeutet, dass im Vergleich folgendes auftreten würde.

// Comparison with 64 Bit Values

function comparisonWith64BitValues(a64, b64)
{
    //
    // No auto-conversion occurs here.  This is an *EFFECTIVE* value comparison.  This works with ordinals with above 53-bits of precision.
    //
    var areEqual = (a64 == b64);
    host.diagnostics.debugLog("areEqual   >> ", areEqual, "\n");
    var areNotEqual = (a64 != b64);
    host.diagnostics.debugLog("areNotEqual   >> ", areNotEqual, "\n");

    //
    // Auto-conversion occurs here.  This will throw if a64 does not pack into a JavaScript number with no loss of precision.
    //
    var isEqualTo42 = (a64 == 42);
    host.diagnostics.debugLog("isEqualTo42   >> ", isEqualTo42, "\n");
    var isLess = (a64 < b64);
    host.diagnostics.debugLog("isLess   >> ", isLess, "\n");

Verwenden Sie einen Text-Editor wie Editor, um eine Textdatei mit dem Namen ComparisonWith64BitValues.js zu erstellen.

Verwenden Sie den Befehl ".scriptload", um das Skript zu laden.

0:000> .scriptload c:\WinDbg\Scripts\ComparisonWith64BitValues.js
JavaScript script successfully loaded from 'c:\WinDbg\Scripts\ComparisonWith64BitValues.js'

Um das Arbeiten mit dem Skript etwas bequemer zu gestalten, weisen Sie im Debugger eine Variable zu, die den Inhalt des Skripts mithilfe des dx-Befehls speichert.

0:000> dx @$myScript = Debugger.State.Scripts.comparisonWith64BitValues.Contents

Zunächst werden wir (2^53) - 2 verwenden und sehen, dass sie die erwarteten Werte zurückgibt.

0:001> dx @$myScript.comparisonWith64BitValues(9007199254740990, 9007199254740990)
areEqual   >> true
areNotEqual   >> false
isEqualTo42   >> false
isLess   >> false

Wir werden auch die Zahl 42 als ersten Wert testen, um zu überprüfen, ob der Vergleichsoperator wie erwartet funktioniert.

0:001> dx @$myScript.comparisonWith64BitValues(42, 9007199254740990)
areEqual   >> false
areNotEqual   >> true
isEqualTo42   >> true
isLess   >> true

Anschließend berechnen wir (2^53) -1 =9007199254740991. Dieser Wert gibt den Fehler zurück, der angibt, dass der Konvertierungsprozess die Genauigkeit verliert. Dies ist der größte Wert, der mit den Vergleichsoperatoren im JavaScript-Code verwendet werden kann.

0:000> dx @$myScript.playWith64BitValues(9007199254740990, 9007199254740991)
Error: 64 bit value loses precision on conversion to number

Aufrechterhaltung der Genauigkeit in Vorgängen

Um die Präzision einer Debugger-Erweiterung zu gewährleisten, wird eine Reihe von mathematischen Funktionen auf dem 64-Bit-Bibliothekstyp abgebildet. Wenn die Erweiterung möglicherweise eine Präzision über 53 Bit für eingehende 64-Bit-Werte benötigt, sollten sie die folgenden Methoden verwenden, anstatt sich auf die üblichen Operatoren zu verlassen.

Methodenname Signatur- Beschreibung
asNumber .asNumber() Konvertiert den 64-Bit-Wert in eine JavaScript-Zahl. Wenn der Genauigkeitsverlust auftritt, wird **EINE AUSNAHME AUSGEWORFEN**
convertToNumber .convertToNumber() Konvertiert den 64-Bit-Wert in eine JavaScript-Zahl. Wenn der Genauigkeitsverlust auftritt, wird **KEINE AUSNAHME GEWORFEN**.
ErhalteUnterenTeil .getLowPart() Konvertiert die niedrigeren 32-Bit-Werte des 64-Bit-Werts in eine JavaScript-Zahl.
getHighPart .getHighPart() Konvertiert die höherwertigen 32 Bits des 64-Bit-Werts in eine JavaScript-Zahl.
hinzufügen .add(value) Fügt dem 64-Bit-Wert einen Wert hinzu und gibt das Ergebnis zurück.
Subtrahieren .subtrahieren(Wert) Subtrahiert einen Wert vom 64-Bit-Wert und gibt das Ergebnis zurück.
multiplizieren .multiplizieren(wert) Multipliziert den 64-Bit-Wert mit dem angegebenen Wert und gibt das Ergebnis zurück.
divide .divide(value) Dividiert den 64-Bit-Wert durch den angegebenen Wert und gibt das Ergebnis zurück.
bitwiseAnd .bitwiseAnd(value) Berechnet den bitweisen und des 64-Bit-Werts mit dem angegebenen Wert und gibt das Ergebnis zurück.
bitwiseOr .bitwiseOr(value) Berechnet den bitweisen oder des 64-Bit-Werts mit dem angegebenen Wert und gibt das Ergebnis zurück.
bitwiseXor .bitwiseXor(value) Berechnet den bitweisen xor des 64-Bit-Werts mit dem angegebenen Wert und gibt das Ergebnis zurück.
bitwiseShiftLeft .bitwiseShiftLeft(value) Verschiebt den 64-Bit-Wert um den angegebenen Betrag nach links und gibt das Ergebnis zurück.
bitwiseShiftRight .bitwiseShiftRight(value) Verschiebt den 64-Bit-Wert um den angegebenen Betrag nach rechts und gibt das Ergebnis zurück.
toString .toString([radix]) Wandelt den 64-Bit-Wert in eine Darstellungszeichenfolge im Standardradix (oder im optional bereitgestellten Radix) um.

Diese Methode ist auch verfügbar.

Methodenname Signatur- Beschreibung
compareTo .compareTo(value) Vergleicht den 64-Bit-Wert mit einem anderen 64-Bit-Wert.

JavaScript-Debugging

In diesem Abschnitt wird beschrieben, wie Sie die Skriptdebuggingfunktionen des Debuggers verwenden. Der Debugger unterstützt das Debuggen von JavaScript-Skripts mithilfe des Befehls ".scriptdebug( Debug JavaScript) ".

Hinweis

Um das JavaScript-Debugging mit WinDbg zu verwenden, führen Sie den Debugger als Administrator aus.

Verwenden Sie diesen Beispielcode, um das Debuggen eines JavaScript zu untersuchen. Für diese exemplarische Vorgehensweise benennen wir sie DebuggableSample.js und speichern sie im Verzeichnis "C:\MyScripts".

"use strict";

class myObj
{
    toString()
    {
        var x = undefined[42];
        host.diagnostics.debugLog("BOO!\n");
    }
}

class iterObj
{
    *[Symbol.iterator]()
    {
        throw new Error("Oopsies!");
    }
}

function foo()
{
    return new myObj();
}

function iter()
{
    return new iterObj();
}

function throwAndCatch()
{
    var outer = undefined;
    var someObj = {a : 99, b : {c : 32, d: "Hello World"} };
    var curProc = host.currentProcess;
    var curThread = host.currentThread;

    try
    {
        var x = undefined[42];
    } catch(e) 
    {
        outer = e;
    }

    host.diagnostics.debugLog("This is a fun test\n");
    host.diagnostics.debugLog("Of the script debugger\n");
    var foo = {a : 99, b : 72};
    host.diagnostics.debugLog("foo.a = ", foo.a, "\n");

    return outer;
}

function throwUnhandled()
{
    var proc = host.currentProcess;
    var thread = host.currentThread;
    host.diagnostics.debugLog("Hello...  About to throw an exception!\n");
    throw new Error("Oh me oh my!  This is an unhandled exception!\n");
    host.diagnostics.debugLog("Oh...  this will never be hit!\n");
    return proc;
}

function outer()
{
    host.diagnostics.debugLog("inside outer!\n");
    var foo = throwAndCatch();
    host.diagnostics.debugLog("Caught and returned!\n");
    return foo;
}

function outermost()
{
    var x = 99;
    var result = outer();
    var y = 32;
    host.diagnostics.debugLog("Test\n");
    return result;
}

function initializeScript()
{
    //
    // Return an array of registration objects to modify the object model of the debugger
    // See the following for more details:
    //
    //     https://aka.ms/JsDbgExt
    //
}

Laden Sie das Beispielskript.

.scriptload C:\MyScripts\DebuggableSample.js

Starten Sie aktiv das Debuggen des Skripts mithilfe des Befehls ".scriptdebug" .

0:000> .scriptdebug C:\MyScripts\DebuggableSample.js
>>> ****** DEBUGGER ENTRY DebuggableSample ******
           No active debug event!

>>> Debug [DebuggableSample <No Position>] >

Sobald die Eingabeaufforderung >>> Debug [DebuggableSample <No Position>] > und eine Eingabeanforderung angezeigt werden, befinden Sie sich im Skriptdebugger.

Verwenden Sie den BEFEHL ".help ", um eine Liste von Befehlen in der JavaScript-Debugumgebung anzuzeigen.

>>> Debug [DebuggableSample <No Position>] >.help
Script Debugger Commands (*NOTE* IDs are **PER SCRIPT**):
    ? .................................. Get help
    ? <expr>  .......................... Evaluate expression <expr> and display result
    ?? <expr>  ......................... Evaluate expression <expr> and display result
    |  ................................. List available scripts
    |<scriptid>s  ...................... Switch context to the given script
    bc \<bpid\>  ......................... Clear breakpoint by specified \<bpid\>
    bd \<bpid\>  ......................... Disable breakpoint by specified \<bpid\>
    be \<bpid\>  ......................... Enable breakpoint by specified \<bpid\>
    bl  ................................ List breakpoints
    bp <line>:<column>  ................ Set breakpoint at the specified line and column
    bp <function-name>  ................ Set breakpoint at the (global) function specified by the given name
    bpc  ............................... Set breakpoint at current location
    dv  ................................ Display local variables of current frame
    g  ................................. Continue script
    gu   ............................... Step out
    k  ................................. Get stack trace
    p  ................................. Step over
    q  ................................. Exit script debugger (resume execution)
    sx  ................................ Display available events/exceptions to break on
    sxe <event>  ....................... Enable break on <event>
    sxd <event>  ....................... Disable break on <event>
    t  ................................. Step in
    .attach <scriptId>  ................ Attach debugger to the script specified by <scriptId>
    .detach [<scriptId>]  .............. Detach debugger from the script specified by <scriptId>
    .frame <index>  .................... Switch to frame number <index>
    .f+  ............................... Switch to next stack frame
    .f-  ............................... Switch to previous stack frame
    .help  ............................. Get help

Verwenden Sie den Befehl für den sx-Skriptdebugger , um die Liste der Ereignisse anzuzeigen, die wir abfangen können.

>>> Debug [DebuggableSample <No Position>] >sx              
sx                                                          
    ab  [   inactive] .... Break on script abort            
    eh  [   inactive] .... Break on any thrown exception    
    en  [   inactive] .... Break on entry to the script     
    uh  [     active] .... Break on unhandled exception     

Verwenden Sie den Skriptdebuggerbefehl sxe, um Unterbrechung beim Eintritt zu aktivieren, damit das Skript in den Skriptdebugger wechselt, sobald irgendein Code darin ausgeführt wird.

>>> Debug [DebuggableSample <No Position>] >sxe en          
sxe en                                                      
Event filter 'en' is now active                             

Beenden Sie den Skriptdebugger, und wir führen einen Funktionsaufruf in das Skript durch, das in den Debugger fällt.

>>> Debug [DebuggableSample <No Position>] >q

An diesem Punkt befinden Sie sich wieder im normalen Debugger. Führen Sie den folgenden Befehl aus, um das Skript aufzurufen.

dx @$scriptContents.outermost()

Jetzt befinden Sie sich wieder im Skriptdebugger und haben in der ersten Zeile der äußersten JavaScript-Funktion haltgemacht.

>>> ****** SCRIPT BREAK DebuggableSample [BreakIn] ******   
           Location: line = 73, column = 5                  
           Text: var x = 99                                 

>>> Debug [DebuggableSample 73:5] >                         

Zusätzlich zur Anzeige des Haltepunkts im Debugger erhalten Sie Informationen zu der Zeile (73) und der Spalte (5), in der der Haltepunkt stattgefunden hat, sowie den relevanten Codeausschnitt des Quellcodes: var x = 99.

Lassen Sie uns ein paar Schritte machen und an eine andere Stelle im Skript gelangen.

    p
    t
    p
    t
    p
    p

An diesem Punkt sollten Sie in die throwAndCatch-Methode in Zeile 34 unterteilt werden.

...
>>> ****** SCRIPT BREAK DebuggableSample [Step Complete] ******                       
           Location: line = 34, column = 5                                            
           Text: var curProc = host.currentProcess                                    

Sie können dies überprüfen, indem Sie eine Stapelablaufverfolgung ausführen.

>>> Debug [DebuggableSample 34:5] >k                                                  
k                                                                                     
    ##  Function                         Pos    Source Snippet                        
-> [00] throwAndCatch                    034:05 (var curProc = host.currentProcess)   
   [01] outer                            066:05 (var foo = throwAndCatch())           
   [02] outermost                        074:05 (var result = outer())                

Von hier aus können Sie den Wert von Variablen untersuchen.

>>> Debug [DebuggableSample 34:5] >??someObj                
??someObj                                                   
someObj          : {...}                                    
    __proto__        : {...}                                
    a                : 0x63                                 
    b                : {...}                                
>>> Debug [DebuggableSample 34:5] >??someObj.b              
??someObj.b                                                 
someObj.b        : {...}                                    
    __proto__        : {...}                                
    c                : 0x20                                 
    d                : Hello World                          

Lassen Sie uns einen Haltepunkt in der aktuellen Codezeile festlegen und sehen, welche Haltepunkte jetzt festgelegt sind.

>>> Debug [DebuggableSample 34:5] >bpc                      
bpc                                                         
Breakpoint 1 set at 34:5                                    
>>> Debug [DebuggableSample 34:5] >bl                       
bl                                                          
      Id State    Pos                                       
       1 enabled  34:5                                      

Von hier aus deaktivieren wir das Eintragsereignis (en) mithilfe des Skriptdebuggerbefehls sxd .

>>> Debug [DebuggableSample 34:5] >sxd en                                                                              
sxd en                                                                                                                 
Event filter 'en' is now inactive                                                                                      

Und dann einfach loslegen und das Skript bis zum Ende fortsetzen lassen.

>>> Debug [DebuggableSample 34:5] >g                                                                                   
g                                                                                                                      
This is a fun test                                                                                                     
Of the script debugger                                                                                                 
foo.a = 99                                                                                                             
Caught and returned!                                                                                                   
Test                                                                                                                   
...

Führen Sie die Skriptmethode erneut aus, und beobachten Sie, wie unser Haltepunkt erreicht wird.

0:000> dx @$scriptContents.outermost()                                                
inside outer!                                                                         
>>> ****** SCRIPT BREAK DebuggableSample [Breakpoint 1] ******                        
           Location: line = 34, column = 5                                            
           Text: var curProc = host.currentProcess                                    

Zeigen Sie den Aufrufstapel an.

>>> Debug [DebuggableSample 34:5] >k                                                  
k                                                                                     
    ##  Function                         Pos    Source Snippet                        
-> [00] throwAndCatch                    034:05 (var curProc = host.currentProcess)   
   [01] outer                            066:05 (var foo = throwAndCatch())           
   [02] outermost                        074:05 (var result = outer())                

An diesem Punkt möchten wir das Debuggen dieses Skripts beenden, daher lösen wir die Verbindung dazu.

>>> Debug [DebuggableSample 34:5] >.detach                  
.detach                                                     
Debugger has been detached from script!                     

Geben Sie dann q ein, um zu beenden.

q                                                           
This is a fun test                                          
Of the script debugger                                      
foo.a = 99                                                  
Caught and returned!                                        
Test                                                        

Durch das erneute Ausführen der Funktion wird der Debugger nicht mehr ausgelöst.

0:007> dx @$scriptContents.outermost()
inside outer!
This is a fun test
Of the script debugger
foo.a = 99
Caught and returned!
Test

JavaScript in VS-Code – Hinzufügen von IntelliSense

Wenn Sie mit den Debugger-Datenmodellobjekten in VS Code arbeiten möchten, können Sie eine Definitionsdatei verwenden, die in den Windows-Entwicklungskits verfügbar ist. Die IntelliSense-Definitionsdatei bietet Unterstützung für alle Host.*-Debuggerobjekt-APIs. Wenn Sie das Kit im Standardverzeichnis auf einem 64-Bit-PC installiert haben, befindet es sich hier:

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\winext\JsProvider.d.ts

So verwenden Sie die IntelliSense-Definitionsdatei in VS Code:

  1. Suchen der Definitionsdatei – JSProvider.d.ts

  2. Kopieren Sie die Definitionsdatei in denselben Ordner wie Ihr Skript.

  3. Fügen Sie /// <reference path="JSProvider.d.ts" /> am Anfang der JavaScript-Skriptdatei hinzu.

Mit dieser Referenz in Ihrer JavaScript-Datei gibt VS Code Ihnen automatisch IntelliSense auf den host-APIs, die von JSProvider bereitgestellt werden, zusätzlich zu den Strukturen in Ihrem Skript. Geben Sie z. B. "Host" ein. Und Sie werden IntelliSense für alle verfügbaren APIs des Debuggermodells sehen.

JavaScript-Ressourcen

Im Folgenden finden Sie JavaScript-Ressourcen, die beim Entwickeln von JavaScript-Debuggingerweiterungen hilfreich sein können.

Siehe auch

JavaScript-Debuggerbeispielskripts

Native Objekte in JavaScript-Erweiterungen