Freigeben über


Debugger-Datenmodell C++ – Scripting

In diesem Thema wird beschrieben, wie Sie das Debuggerdatenmodell C++-Debuggerdatenmodell-C++-Skripting verwenden, um die Automatisierung mit dem Debuggermodul mithilfe von Skripts zu unterstützen.

Skriptverwaltung im Debuggerdatenmodell

Zusätzlich zur Rolle des Datenmodell-Managers als zentrale Autorität zur Objekterstellung und Erweiterbarkeit ist er auch für die Verwaltung eines abstrakten Konzepts von Skripts verantwortlich. Aus Sicht des Skript-Managers des Datenmodell-Managers ist ein Skript etwas, das dynamisch geladen, entladen und potenziell von einem Anbieter gedebuggt werden kann, um neue Funktionen für das Datenmodell zu erweitern oder bereitzustellen.

Ein Skriptanbieter ist eine Komponente, die eine Sprache (z. B. NatVis, JavaScript usw.) mit dem Datenmodell verbindet. Sie registriert eine oder mehrere Dateierweiterungen (z.B.: ". NatVis", ".js") die vom Anbieter verarbeitet werden, sodass ein Debuggerclient oder eine Benutzeroberfläche das Laden von Skriptdateien mit dieser bestimmten Erweiterung durch Delegierung an den Anbieter ermöglicht.

Core Script Manager: IDataModelScriptManager

Die Kernskript-Manager-Schnittstelle ist wie folgt definiert.

DECLARE_INTERFACE_(IDataModelScriptManager, IUnknown)
{
    STDMETHOD(GetDefaultNameBinder)(_COM_Outptr_ IDataModelNameBinder **ppNameBinder) PURE;
    STDMETHOD(RegisterScriptProvider)(_In_ IDataModelScriptProvider *provider) PURE;
    STDMETHOD(UnregisterScriptProvider)(_In_ IDataModelScriptProvider *provider) PURE;
    STDMETHOD(FindProviderForScriptType)(_In_ PCWSTR scriptType, _COM_Outptr_ IDataModelScriptProvider **provider) PURE;
    STDMETHOD(FindProviderForScriptExtension)(_In_ PCWSTR scriptExtension, _COM_Outptr_ IDataModelScriptProvider **provider) PURE;
    STDMETHOD(EnumerateScriptProviders)(_COM_Outptr_ IDataModelScriptProviderEnumerator **enumerator) PURE;
}

GetDefaultNameBinder

Die GetDefaultNameBinder-Methode gibt den Standardnamenordner des Datenmodells zurück. Ein Namensordner ist eine Komponente, die einen Namen im Kontext eines Objekts aufgelöst. Beispielsweise wird aufgrund des Ausdrucks "foo.bar" ein Namensbinder aufgerufen, um die Namensleiste im Kontext von Objekt foo aufzulösen. Der hier zurückgegebene Ordner folgt einer Reihe von Standardregeln für das Datenmodell. Skriptanbieter können diesen Ordner verwenden, um Konsistenz bei der Namensauflösung für alle Anbieter bereitzustellen.

RegisterScriptProvider-

Die RegisterScriptProvider-Methode informiert das Datenmodell darüber, dass ein neuer Skriptanbieter vorhanden ist, der eine neue Sprache mit dem Datenmodell überbrücken kann. Wenn diese Methode aufgerufen wird, ruft der Skript-Manager sofort den angegebenen Skriptanbieter zurück und fragt nach den Eigenschaften der von ihm verwalteten Skripts. Wenn bereits ein Anbieter unter dem Namen oder der Dateierweiterung registriert ist, den der angegebene Skriptanbieter angibt, schlägt diese Methode fehl. Nur ein einzelner Skriptanbieter kann als Handler für einen bestimmten Namen oder eine bestimmte Dateierweiterung registriert werden.

UnregisterScriptProvider-

Mit der UnregisterScriptProvider-Methode wird ein Aufruf der RegisterScriptProvider-Methode rückgängig. Der Name und die Dateierweiterung, die vom anbieter für inpassierten Skripts angegeben wird, wird ihm nicht mehr zugeordnet. Es ist wichtig zu beachten, dass es auch nach der Registrierung eine erhebliche Anzahl ausstehender COM-Verweise auf den Skriptanbieter geben kann. Diese Methode verhindert nur das Laden/Erstellen von Skripts des Typs, den der angegebene Skriptanbieter verwaltet. Wenn ein von diesem Anbieter geladenes Skript noch geladen oder das Objektmodell des Debuggers (oder Datenmodells) manipuliert wurde, verfügen diese Manipulationen möglicherweise noch über Verweise auf das Skript. Es können Datenmodelle, Methoden oder Objekte vorhanden sein, die direkt auf Konstrukte im Skript verweisen. Ein Skriptanbieter muss darauf vorbereitet sein.

FindProviderForScriptType-

Die FindProviderForScriptType-Methode durchsucht den Skript-Manager nach einem Anbieter, der wie in dieser Methode angegeben eine Skripttypzeichenfolge aufweist. Wenn eine nicht gefunden werden kann, schlägt diese Methode fehl. andernfalls wird dieser Skriptanbieter an den Aufrufer zurückgegeben.

EnumerateScriptProviders

Die EnumerateScriptProviders-Methode gibt einen Enumerator zurück, der alle Skriptanbieter aufzählt, die über einen vorherigen Aufruf der RegisterScriptProvider-Methode beim Skript-Manager registriert wurden.

Script Provider Enumeration: IDataModelScriptProviderEnumerator

Die EnumerateScriptProviders-Methode gibt einen Enumerator des folgenden Formulars zurück:

DECLARE_INTERFACE_(IDataModelScriptProviderEnumerator, IUnknown)
{
    STDMETHOD(Reset)() PURE;
    STDMETHOD(GetNext)(_COM_Outptr_ IDataModelScriptProvider **provider) PURE;
}

zurücksetzen

Mit der Reset-Methode wird der Enumerator an die Position verschoben, an der es sich befand, bevor das erste Element zurückgegeben wurde.

GetNext-

Mit der GetNext-Methode wird der Enumerator ein Element weiterleiten und den Skriptanbieter zurückgeben, der sich an diesem Element befindet. Wenn der Enumerator auf das Ende der Enumeration trifft, wird E_BOUNDS zurückgegeben. Das Aufrufen der GetNext-Methode nach erhalt dieses Fehlers wird weiterhin E_BOUNDS unbegrenzt zurückgegeben.

Debugger-Datenmodell-C++-Hostschnittstellen für Skripting

Rolle des Hosts in Scripting-

Der Debughost macht eine Reihe von sehr niedrigen Schnittstellen verfügbar, um die Art des Typsystems seiner Debugziele zu verstehen, Ausdrücke in der Sprache seiner Debugziele auszuwerten usw. Normalerweise wird es nicht mit Konstrukten auf höherer Ebene wie Skripting behandelt. Dies bleibt der gesamten Debuggeranwendung oder Erweiterungen überlassen, die diese Funktionen bereitstellen. Es gibt jedoch eine Ausnahme. Jeder Debughost, der an der allgemeinen Skripterstellungserfahrung des Datenmodells teilnehmen möchte, muss einige einfache Schnittstellen implementieren, um Kontexte für Skripts bereitzustellen. Der Debughost ist tatsächlich in der Kontrolle darüber, wo die Skriptumgebung Funktionen und andere bereitgestellte Skriptfunktionen im Namespace des Datenmodells platzieren soll. Wenn sie an diesem Prozess beteiligt sind, kann der Host beispielsweise die Verwendung solcher Funktionen in seinem Ausdrucksauswertung zulassen (oder nicht). Hier sind die schnittstellen, die aus der Perspektive des Hosts beteiligt sind:

Schnittstelle BESCHREIBUNG
IDebugHostScriptHost Die Schnittstelle, die die Funktion des Debughosts angibt, an der Skriptumgebung teilzunehmen. Diese Schnittstelle ermöglicht die Erstellung von Kontexten, die Skriptmodule darüber informieren, wo Objekte platziert werden sollen.
IDataModelScriptHostContext Eine Hostschnittstelle, die vom Skriptanbieter als Container für den Inhalt des Skripts verwendet wird. Wie der Inhalt einer anderen Skriptoberfläche als die Manipulationen, die sie für das Objektmodell der Debuggeranwendung ausführt, bis zum jeweiligen Debughost gehört. Diese Schnittstelle ermöglicht es dem Skriptanbieter, Informationen darüber abzurufen, wo der Inhalt platziert werden soll. Weitere Informationen finden Sie unter Datenmodell-C++-Skriptschnittstellen weiter unten in diesem Thema.

Skripthost des Debughosts: IDebugHostScriptHost-

Die IDebugHostScriptHost-Schnittstelle ist die Schnittstelle, die von einem Skriptanbieter verwendet wird, um einen Kontext vom Debughost für ein neu erstelltes Skript abzurufen. Dieser Kontext enthält ein Objekt (bereitgestellt vom Debughost), in dem der Skriptanbieter alle Brücken zwischen dem Datenmodell und der Skriptumgebung platzieren kann. Solche Brücken können beispielsweise Datenmodellmethoden sein, die Skriptfunktionen aufrufen. Dadurch kann ein Aufrufer auf der Datenmodellseite Skriptmethoden aufrufen, indem die Call-Methode auf der IModelMethod-Schnittstelle verwendet wird.

Die IDebugHostScriptHost-Schnittstelle wird wie folgt definiert.

DECLARE_INTERFACE_(IDebugHostScriptHost, IUnknown)
{
    STDMETHOD(CreateContext)(_In_ IDataModelScript* script, _COM_Outptr_ IDataModelScriptHostContext** scriptContext) PURE;
}

CreateContext-

Die CreateContext-Methode wird von einem Skriptanbieter aufgerufen, um einen neuen Kontext zu erstellen, in dem der Inhalt des Skripts platziert werden soll. Dieser Kontext wird durch die IDataModelScriptHostContext-Schnittstelle dargestellt, die im Detail auf der Seite "Datenmodell-C++-Skriptschnittstellen" beschrieben wird.

Debuggerdatenmodell-C++-Skriptschnittstellen

Skript- und Skriptschnittstellen

Die allgemeine Architektur des Datenmodells ermöglicht es einem Drittanbieter, eine Brücke zwischen einer bestimmten Sprache und dem Objektmodell des Datenmodells zu definieren. In der Regel ist die Zubrückungssprache eine Skriptsprache, da die Umgebung des Datenmodells sehr dynamisch ist. Eine Komponente, die diese Brücke zwischen einer Sprache und dem Objektmodell des Datenmodells definiert und implementiert, wird als Skriptanbieter bezeichnet. Bei der Initialisierung registriert sich ein Skriptanbieter mit dem Skript-Manager-Teil des Datenmodell-Managers und jeder Schnittstelle, die die Erweiterbarkeit verwaltet, ermöglicht anschließend die Bearbeitung, das Laden, Entladen und potenziell das Debuggen von Skripts, die in die sprache geschrieben wurden, die der Skriptanbieter verwaltet.

Beachten Sie, dass Debuggingtools für Windows derzeit zwei Skriptanbieter definieren.

  • Der NatVis-Anbieter. Dieser Anbieter ist in DbgEng.dll und Brücken zwischen NatVis XML- und Datenmodellen eingebettet und ermöglicht die Visualisierung nativer/spracheigener Datentypen.
  • Der JavaScript-Anbieter. Dieser Anbieter ist in einer Legacydebuggererweiterung enthalten: JsProvider.dll. Es brücken zwischen Skripts, die in der JavaScript-Sprache und dem Datenmodell geschrieben wurden, wodurch beliebige Formen der Debuggersteuerung und Erweiterbarkeit ermöglicht werden.

Neue Anbieter können geschrieben werden, die andere Sprachen (z. B. Python usw.) mit dem Datenmodell überbrücken. Dies würde derzeit zu Ladezwecken in Legacydebuggererweiterungen gekapselt werden. Der Skriptanbieter selbst sollte die Abhängigkeit mit älteren Modulschnittstellen minimieren und nur die Datenmodell-APIs verwenden, sofern möglich. Dadurch kann der Anbieter mit deutlich größerer Leichtigkeit in andere Umgebungen portierbar gemacht werden.

Es gibt zwei Klassen von Schnittstellen im Zusammenhang mit Skriptanbietern. Die erste Klasse von Schnittstellen dient der allgemeinen Verwaltung von Skriptanbietern und den von ihnen verwalteten Skripts. Die zweite Schnittstellenklasse dient zur Unterstützung des Skriptdebuggings. Während die Unterstützung für den ersten Satz obligatorisch ist, ist die Unterstützung für die zweite optional und kann für jeden Anbieter nicht sinnvoll sein.

Die allgemeinen Verwaltungsschnittstellen sind:

Schnittstelle BESCHREIBUNG
IDataModelScriptProvider Die Kernschnittstelle, die ein Skriptanbieter implementieren muss. Dies ist die Schnittstelle, die beim Skript-Manager-Teil des Datenmodell-Managers registriert ist, um die Unterstützung eines bestimmten Skripttyps des Anbieters anzukündigen und sich bei einer bestimmten Dateierweiterung zu registrieren.
IDataModelScript Eine Abstraktion eines bestimmten Skripts, das vom Anbieter verwaltet wird. Jedes Skript, das geladen oder bearbeitet wird, verfügt über eine separate IDataModelScript-Instanz.
IDataModelScriptClient Eine Clientschnittstelle, die vom Skriptanbieter verwendet wird, um Informationen an eine Benutzeroberfläche zu übermitteln. Skriptanbieter implementieren diese Schnittstelle nicht. Die Anwendung, die das Datenmodell hosten soll, das Skriptanbieter verwenden möchte. Ein Skriptanbieter ruft Methoden des Skriptclients auf, um Status, Fehler usw. zu melden...
IDataModelScriptHostContext Eine Hostschnittstelle, die vom Skriptanbieter als Container für den Inhalt des Skripts verwendet wird. Wie der Inhalt einer anderen Skriptoberfläche als die Manipulationen, die sie für das Objektmodell der Debuggeranwendung ausführt, bis zum jeweiligen Debughost gehört. Diese Schnittstelle ermöglicht es dem Skriptanbieter, Informationen darüber abzurufen, wo der Inhalt platziert werden soll.
IDataModelScriptTemplate Skriptanbieter können eine oder mehrere Vorlagen bereitstellen, die als Ausgangspunkt für Benutzer zum Erstellen von Skripts dienen. Eine Debuggeranwendung, die einen integrierten Editor bereitstellt, kann neue Skripts mit Vorlageninhalten vorab ausfüllen, wie vom Anbieter über diese Schnittstelle angekündigt.
IDataModelScriptTemplateEnumerator Eine Enumerationsschnittstelle, die der Skriptanbieter implementiert, um alle unterstützten Vorlagen anzukündigen.
IDataModelNameBinder Ein Namensbinder - ein Objekt, das einen Namen in einem Kontext einem Wert zuordnen kann. Bei einem bestimmten Ausdruck wie "foo.bar" kann ein Namensbinder den Namen "bar" im Kontext des Objekts "foo" binden und einen Wert oder Einen Verweis darauf erzeugen. Namenmappen werden in der Regel nicht von einem Skriptanbieter implementiert. Stattdessen kann der Standardordner aus dem Datenmodell abgerufen und vom Skriptanbieter verwendet werden.

Die Debugschnittstellen sind:

Schnittstelle BESCHREIBUNG
IDataModelScriptDebug Die Kernschnittstelle, die ein Skriptanbieter bereitstellen muss, um ein Skript debuggen zu können. Die Implementierungsklasse der IDataModelScript-Schnittstelle muss QueryInterface für IDataModelScriptDebug verwenden, wenn das Skript debuggierbar ist.
IDataModelScriptDebugClient Die Benutzeroberfläche, die die Funktion des Skriptdebuggings bereitstellen möchte, implementiert die IDataModelScriptDebugClient-Schnittstelle. Der Skriptanbieter verwendet diese Schnittstelle, um Debuginformationen hin und her zu übergeben (z. B.: Ereignisse, die auftreten, Haltepunkte usw....)
IDataModelScriptDebugStack Der Skriptanbieter implementiert diese Schnittstelle, um den Begriff eines Aufrufstapels für den Skriptdebugger verfügbar zu machen.
IDataModelScriptDebugStackFrame Der Skriptanbieter implementiert diese Schnittstelle, um den Begriff eines bestimmten Stapelframes innerhalb des Aufrufstapels verfügbar zu machen.
IDataModelScriptDebugVariableSetEnumerator Der Skriptanbieter implementiert diese Schnittstelle, um eine Reihe von Variablen verfügbar zu machen. Dieser Satz kann den Satz von Parametern für eine Funktion, den Satz lokaler Variablen oder den Satz von Variablen innerhalb eines bestimmten Bereichs darstellen. Die genaue Bedeutung hängt davon ab, wie die Schnittstelle erworben wurde.
IDataModelScriptDebugBreakpoint Der Skriptanbieter implementiert diese Schnittstelle, um den Begriff und die Kontrolle eines bestimmten Haltepunkts innerhalb des Skripts verfügbar zu machen.
IDataModelScriptDebugBreakpointEnumerator Der Skriptanbieter implementiert dies, um alle Haltepunkte aufzulisten, die derzeit innerhalb des Skripts vorhanden sind (unabhängig davon, ob aktiviert oder nicht).

Core Script Provider: IDataModelScriptProvider

Jede Erweiterung, die ein Skriptanbieter sein möchte, muss eine Implementierung der IDataModelScriptProvider-Schnittstelle bereitstellen und mit dem Skript-Manager-Teil des Datenmodell-Managers über die RegisterScriptProvider-Methode registrieren. Diese Kernschnittstelle, die implementiert werden muss, ist wie folgt definiert.

DECLARE_INTERFACE_(IDataModelScriptProvider, IUnknown)
{
    STDMETHOD(GetName)(_Out_ BSTR *name) PURE;
    STDMETHOD(GetExtension)(_Out_ BSTR *extension) PURE;
    STDMETHOD(CreateScript)(_COM_Outptr_ IDataModelScript **script) PURE;
    STDMETHOD(GetDefaultTemplateContent)(_COM_Outptr_ IDataModelScriptTemplate **templateContent) PURE;
    STDMETHOD(EnumerateTemplates)(_COM_Outptr_ IDataModelScriptTemplateEnumerator **enumerator) PURE;
}

GetName-

Die GetName-Methode gibt den Namen des Typs (oder der Sprache von) Skripts zurück, die der Anbieter als über die SysAllocString-Methode zugeordnete Zeichenfolge verwaltet. Der Aufrufer ist dafür verantwortlich, die zurückgegebene Zeichenfolge über SysFreeString freizugeben. Beispiele für Zeichenfolgen, die von dieser Methode zurückgegeben werden können, sind "JavaScript" oder "NatVis". Die zurückgegebene Zeichenfolge wird wahrscheinlich auf der Benutzeroberfläche der Debuggeranwendung angezeigt, die das Datenmodell hostet. Es können keine zwei Skriptanbieter denselben Namen zurückgeben (Groß-/Kleinschreibung wird nicht beachtet).

GetExtension-

Die GetExtension-Methode gibt die Dateierweiterung für Skripts zurück, die von diesem Anbieter verwaltet werden (ohne den Punkt), als Zeichenfolge, die über die SysAllocString-Methode zugewiesen wird. Die Debuggeranwendung, die das Datenmodell (mit Skriptunterstützung) hosten, delegiert das Öffnen von Skriptdateien mit dieser Erweiterung an den Skriptanbieter. Der Aufrufer ist dafür verantwortlich, die zurückgegebene Zeichenfolge über SysFreeString freizugeben. Beispiele für Zeichenfolgen, die von dieser Methode zurückgegeben werden können, sind "js" oder "NatVis".

CreateScript-

Die CreateScript-Methode wird aufgerufen, um ein neues Skript zu erstellen. Der Skriptanbieter muss ein neues und leeres Skript zurückgeben, das durch die zurückgegebene IDataModelScript-Schnittstelle dargestellt wird, wenn diese Methode aufgerufen wird. Beachten Sie, dass diese Methode unabhängig davon aufgerufen wird, ob eine Benutzeroberfläche ein neues leeres Skript zum Bearbeiten durch den Benutzer erstellt oder ob die Debuggeranwendung ein Skript vom Datenträger lädt. Der Anbieter wird nicht an Datei-E/A beteiligt. Sie verarbeitet lediglich die Anforderungen der Hostanwendung über Datenströme, die an Methoden in IDataModelScript übergeben werden.

GetDefaultTemplateContent-

Die GetDefaultTemplateContent-Methode gibt eine Schnittstelle für den Standardvorlageninhalt des Anbieters zurück. Dies ist Inhalt, den der Skriptanbieter in einem Bearbeitungsfenster für ein neu erstelltes Skript vorab ausgefüllt haben möchte. Wenn der Skriptanbieter keine Vorlagen aufweist (oder keine Vorlageninhalte enthält, die als Standardinhalt festgelegt sind), gibt der Skriptanbieter möglicherweise E_NOTIMPL von dieser Methode zurück.

EnumerateTemplates

Die EnumerateTemplates-Methode gibt einen Enumerator zurück, der die Vielzahl von Vorlagen aufzählen kann, die vom Skriptanbieter bereitgestellt werden. Vorlageninhalt ist das, was der Skriptanbieter beim Erstellen eines neuen Skripts in ein Bearbeitungsfenster "vorgefüllt" werden möchte. Wenn mehrere verschiedene Vorlagen unterstützt werden, können diese Vorlagen benannt werden (z. B. "Imperatives Skript", "Erweiterungsskript") und die Debuggeranwendung, in der das Datenmodell gehostet wird, wählen, wie die "Vorlagen" dem Benutzer präsentiert werden sollen.

die Core Script Interface: IDataModelScript

Die Hauptschnittstelle, die ein einzelnes Skript verwaltet, das vom Anbieter implementiert wird, ist die IDataModelScript-Schnittstelle. Eine Komponente, die diese Schnittstelle implementiert, wird zurückgegeben, wenn der Client ein neues leeres Skript erstellen möchte und die CreateScript-Methode für IDataModelScriptProvider aufruft.

Jedes skript, das vom Anbieter erstellt wird, sollte sich in einem unabhängigen Silo befindet. Ein Skript sollte sich nicht auf ein anderes Skript auswirken können, außer durch explizite Interaktion mit externen Objekten über das Datenmodell. Zwei Skripts können z. B. einige Typen oder Konzepte erweitern (z. B. die Vorstellung des Debuggers, was ein Prozess ist). Beide Skripts können dann über das externe Prozessobjekt auf die Felder der anderen zugreifen.

Die Schnittstelle wird wie folgt definiert.

DECLARE_INTERFACE_(IDataModelScript, IUnknown)
{
    STDMETHOD(GetName)(_Out_ BSTR *scriptName) PURE;
    STDMETHOD(Rename)(_In_ PCWSTR scriptName) PURE;
    STDMETHOD(Populate)(_In_ IStream *contentStream) PURE;
    STDMETHOD(Execute)(_In_ IDataModelScriptClient *client) PURE;
    STDMETHOD(Unlink)() PURE;
    STDMETHOD(IsInvocable)(_Out_ bool *isInvocable) PURE;
    STDMETHOD(InvokeMain)(_In_ IDataModelScriptClient *client) PURE; 
}

GetName-

Die GetName-Methode gibt den Namen des Skripts als zugeordnete Zeichenfolge über die SysAllocString-Funktion zurück. Wenn das Skript noch keinen Namen hat, sollte die Methode einen NULL-BSTR zurückgeben. Es sollte in diesem Fall nicht scheitern. Wenn das Skript explizit über einen Aufruf der Rename-Methode umbenannt wird, sollte die GetName-Methode den neu zugewiesenen Namen zurückgeben.

umbenennen

Die Rename-Methode weist dem Skript einen neuen Namen zu. Es liegt in der Verantwortung der Skriptimplementierung, diesen Namen zu speichern und bei jedem Aufruf der GetName-Methode zurückzugeben. Dies wird häufig aufgerufen, wenn sich eine Benutzeroberfläche für "Speichern unter" für einen neuen Namen entscheidet. Beachten Sie, dass sich das Umbenennen des Skripts möglicherweise darauf auswirken kann, wo die Hostinganwendung den Inhalt des Skripts projiziert.

auffüllen

Die Populate-Methode wird vom Client aufgerufen, um den "Inhalt" des Skripts zu ändern oder zu synchronisieren. Es handelt sich um die Benachrichtigung, die an den Skriptanbieter gesendet wird, dass sich der Code des Skripts geändert hat. Es ist wichtig zu beachten, dass diese Methode keine Ausführung des Skripts oder Änderungen an einem der Objekte verursacht, die das Skript bearbeitet. Dies ist lediglich eine Benachrichtigung an den Skriptanbieter, dass sich der Inhalt des Skripts geändert hat, damit er seinen eigenen internen Zustand synchronisieren kann.

ausführen

Die Execute-Methode führt den Inhalt des Skripts wie durch den letzten erfolgreichen Auffüllaufruf diktieren aus und ändert das Objektmodell des Debuggers entsprechend diesem Inhalt. Wenn die Sprache (oder der Skriptanbieter) eine "Hauptfunktion" definiert – eine, die der Autor aufgerufen werden soll, wenn er auf eine imaginäre Schaltfläche "Skript ausführen" in einer Benutzeroberfläche klickt - wird diese "Hauptfunktion" während eines Execute-Vorgangs nicht aufgerufen. Der Execute-Vorgang kann nur als Initialisierungs- und Objektmodellmanipulation betrachtet werden (z. B. Ausführen von Stammcode und Einrichten von Erweiterungspunkten).

Verknüpfung aufheben

Mit der Unlink-Methode wird der Execute-Vorgang rückgängig. Alle Während der Ausführung des Skripts festgelegten Objektmodellmanipulations- oder Erweiterungspunkte werden rückgängig gemacht. Nach einem Vorgang zum Aufheben der Verknüpfung kann das Skript über einen Aufruf von Execute erneut ausgeführt oder freigegeben werden.

IsInvocable

Die IsInvocable-Methode gibt zurück, ob das Skript aufrufbar ist – d. h., ob es eine "Hauptfunktion" hat, die von der Sprache oder dem Anbieter definiert ist. Eine solche "Hauptfunktion" ist konzeptionell etwas, das der Skriptautor aufrufen würde, wenn eine imaginäre Schaltfläche "Execute Script" in einer Benutzeroberfläche gedrückt wurde.

InvokeMain-

Wenn das Skript über eine "Hauptfunktion" verfügt, die von einem Ui-Aufruf ausgeführt werden soll, gibt es eine solche über eine echte Rückgabe aus der IsInvocable-Methode an. Die Benutzeroberfläche kann dann die InvokeMain-Methode aufrufen, um das Skript tatsächlich aufzurufen. Beachten Sie, dass dies von Execute unterscheidet, die den gesamten Stammcode ausführt und das Skript mit dem Namespace des zugrunde liegenden Hosts verbindet.

**Der Skriptclient: IDataModelScriptClient **

Eine Anwendung, die das Datenmodell hostet, das Skripts verwalten möchte und über eine Benutzeroberfläche (ob grafisch oder konsole) um diese Vorstellung herum implementiert die IDataModelScriptClient-Schnittstelle. Diese Schnittstelle wird während der Ausführung oder Aufruf oder eines Skripts an einen beliebigen Skriptanbieter übergeben, um Fehler- und Ereignisinformationen an die Benutzeroberfläche zurückzugeben.

Die IDataModelScriptClient-Schnittstelle ist wie folgt definiert.

DECLARE_INTERFACE_(IDataModelScriptClient, IUnknown)
{
   STDMETHOD(ReportError)(_In_ ErrorClass errClass, _In_ HRESULT hrFail, _In_opt_ PCWSTR message, _In_ ULONG line, _In_ ULONG position) PURE;
}

Fehler melden

Wenn während der Ausführung oder Aufruf des Skripts ein Fehler auftritt, ruft der Skriptanbieter die ReportError-Methode auf, um die Benutzeroberfläche des Fehlers zu benachrichtigen.

Hostkontext für ein Skript: IDataModelScriptHostContext

Der Debughost hat einfluss darauf, wie und wo er Datenmodellskriptinhalte projektiert. Es wird erwartet, dass jedes Skript den Host nach einem Kontext fragt, in dem Brücken zum Skript platziert werden (z. B.: Funktionsobjekte, die aufgerufen werden können usw.). Dieser Kontext wird abgerufen, indem die CreateContext-Methode für IDebugHostScriptHostHost aufgerufen und ein IDataModelScriptHostContext abgerufen wird.

Die IDataModelScriptHostContext-Schnittstelle wird wie folgt definiert.

DECLARE_INTERFACE_(IDataModelScriptHostContext, IUnknown)
{
   STDMETHOD(NotifyScriptChange)(_In_ IDataModelScript* script, _In_ ScriptChangeKind changeKind) PURE;
   STDMETHOD(GetNamespaceObject)(_COM_Outptr_ IModelObject** namespaceObject) PURE;
}

NotifyScriptChange-

Es ist erforderlich, dass ein Skriptanbieter den Debughost bei bestimmten Vorgängen benachrichtigt, die mit einem Methodenaufruf an die NotifyScriptChange-Methode im zugeordneten Kontext auftreten. Solche Vorgänge werden als Member der ScriptChangeKind-Aufzählung definiert.

GetNamespaceObject-

Die GetNamespaceObject-Methode gibt ein Objekt zurück, in das der Skriptanbieter beliebige Brücken zwischen dem Datenmodell und dem Skript platzieren kann. Es ist beispielsweise hier, dass der Skriptanbieter Datenmodellmethodenobjekte (IModelMethod-Schnittstellen in IModelObject) platzieren kann, deren Implementierung aufruft in entsprechend benannte Funktionen im Skript.

Vorlagen für neu erstellte Skripts: IDataModelScriptTemplate

Skriptanbieter, die vorab ausgefüllten Inhalt für neue Skripts präsentieren möchten (z. B. um Benutzern das Schreiben von Skripts in einer Debugger-Benutzeroberfläche zu erleichtern), können dies tun, indem Sie eine oder mehrere Skriptvorlagen bereitstellen. Solche Vorlagen sind Komponenten, die die IDataModelScriptTemplate-Schnittstelle implementieren und entweder über die GetDefaultTemplate-Methode oder die EnumerateTemplates-Methode für den Skriptanbieter zurückgegeben werden.

Die IDataModelScriptTemplate-Schnittstelle wird wie folgt definiert.

DECLARE_INTERFACE_(IDataModelScriptTemplate, IUnknown)
{
   STDMETHOD(GetName)(_Out_ BSTR *templateName) PURE;
   STDMETHOD(GetDescription)(_Out_ BSTR *templateDescription) PURE;
   STDMETHOD(GetContent)(_COM_Outptr_ IStream **contentStream) PURE;
}

GetName-

Die GetName-Methode gibt einen Namen der Vorlage zurück. Dies kann mit E_NOTIMPL fehlschlagen, wenn die Vorlage keinen Namen hat. Die einzelne Standardvorlage (sofern vorhanden) ist nicht erforderlich, um einen Namen zu haben. Alle anderen Vorlagen sind. Diese Namen können in einer Benutzeroberfläche als Teil eines Menüs angezeigt werden, um auszuwählen, welche Vorlage erstellt werden soll.

GetDescription-

Die GetDescription-Methode gibt eine Beschreibung der Vorlage zurück. Eine solche Beschreibung würde dem Benutzer in aussagekräftigeren Schnittstellen angezeigt, um dem Benutzer zu helfen, zu verstehen, was die Vorlage zu tun hat. Die Vorlage gibt möglicherweise E_NOTIMPL von dieser Methode zurück, wenn sie keine Beschreibung enthält.

GetContent

Die GetContent-Methode gibt den Inhalt (oder Code) der Vorlage zurück. Dies würde im Bearbeitungsfenster bereits ausgefüllt werden, wenn ein Benutzer ein neues Skript aus dieser Vorlage erstellt hat. Die Vorlage ist für das Erstellen (und Zurückgeben) eines Standarddatenstroms über den Vom Client abgerufenen Inhalt verantwortlich.

Enumeration des Vorlageninhalts eines Anbieters: IDataModelScriptTemplateEnumerator

Ein Skriptanbieter kann eine oder mehrere Vorlagen bereitstellen, die Inhalte in neu erstellten Skripts auf einer Benutzeroberfläche vorab ausfüllen. Wenn eine dieser Vorlagen bereitgestellt wird, muss der Skriptanbieter einen Enumerator für sie implementieren, der bei einem Aufruf der EnumerateTemplates-Methode zurückgegeben wird.

Diese Enumeration ist eine Implementierung der IDataModelScriptTemplateEnumerator-Schnittstelle und wird wie folgt definiert.

DECLARE_INTERFACE_(IDataModelScriptTemplateEnumerator, IUnknown)
{
   STDMETHOD(Reset)() PURE;
   STDMETHOD(GetNext)(_COM_Outptr_ IDataModelScriptTemplate **templateContent) PURE;
}

zurücksetzen

Mit der Reset-Methode wird der Enumerator auf die Position zurückgesetzt, an der sie sich befand, als sie zum ersten Mal erstellt wurde – bevor die erste Vorlage erstellt wurde.

GetNext-

Die GetNext-Methode verschiebt den Enumerator zur nächsten Vorlage und gibt sie zurück. Am Ende der Aufzählung gibt der Enumerator E_BOUNDS zurück. Sobald die E_BOUNDS Markierung getroffen wurde, erzeugt der Enumerationsgeber weiterhin E_BOUNDS Fehler, bis ein Reset-Aufruf erfolgt.

Auflösen der Bedeutung von Namen: IDataModelNameBinder

Das Datenmodell bietet eine Standardmethode für Skriptanbieter, um die Bedeutung eines bestimmten Namens in einem bestimmten Kontext zu bestimmen (z. B. bestimmen, welche Leiste für foo.bar bedeutet), die über eine Vielzahl von Skriptanbietern hinweg ausgeführt wird. Dieser Mechanismus wird als Namensbinder bezeichnet und wird durch die IDataModelNameBinder-Schnittstelle dargestellt. Ein solcher Sammelordner kapselt eine Reihe von Regeln darüber, wie der Name aufgelöst wird und wie mit der Konfliktauflösung umgegangen wird, bei der ein Name mehrmals für ein Objekt definiert wird. Ein Teil dieser Regeln umfasst z. B. die Auflösung eines projizierten Namens (eines von einem Datenmodell hinzugefügten) anhand eines systemeigenen Namens (eines im Typsystem der zu debuggenden Sprache).

Um einen Grad an Konsistenz bei allen Skriptanbietern zu gewährleisten, stellt der Skript-Manager des Datenmodells einen Standardnamenordner bereit. Dieser Standardnamenordner kann über einen Aufruf der GetDefaultNameBinder-Methode auf der IDataModelScriptManager-Schnittstelle abgerufen werden. Die Namensbinderschnittstelle ist wie folgt definiert.

DECLARE_INTERFACE_(IDataModelNameBinder, IUnknown)
{
   STDMETHOD(BindValue)(_In_ IModelObject* contextObject, _In_ PCWSTR name, _COM_Errorptr_ IModelObject** value, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
   STDMETHOD(BindReference)(_In_ IModelObject* contextObject, _In_ PCWSTR name, _COM_Errorptr_ IModelObject** reference, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
   STDMETHOD(EnumerateValues)(_In_ IModelObject* contextObject, _COM_Outptr_ IKeyEnumerator** enumerator) PURE;
   STDMETHOD(EnumerateReferences)(_In_ IModelObject* contextObject, _COM_Outptr_ IKeyEnumerator** enumerator) PURE;
}

BindValue-

Die BindValue-Methode führt das Äquivalent von contextObject.name für das angegebene Objekt gemäß einer Reihe von Bindungsregeln aus. Das Ergebnis dieser Bindung ist ein Wert. Als Wert kann der zugrunde liegende Skriptanbieter den Wert nicht verwenden, um die Zuordnung zurück zum Namen auszuführen.

BindReference-

Die BindReference-Methode ähnelt BindValue darin, dass sie auch das Äquivalent von contextObject.name für das angegebene Objekt gemäß einer Reihe von Bindungsregeln ausführt. Das Ergebnis der Bindung aus dieser Methode ist jedoch ein Verweis anstelle eines Werts. Als Referenz kann der Skriptanbieter den Verweis verwenden, um die Zuordnung zurück zum Namen auszuführen.

EnumerateValues

Die EnumerateValues-Methode listet den Satz von Namen und Werten auf, die gemäß den Regeln der BindValue-Methode an das Objekt gebunden werden. Im Gegensatz zu den EnumerateKeys, EnumerateValues und ähnlichen Methoden für IModelObject, die mehrere Namen mit demselben Wert zurückgeben können (für Basisklassen, übergeordnete Modelle und ähnliches), gibt dieser Enumerationerator nur den spezifischen Satz von Namen zurück, der mit BindValue und BindReference gebunden wird. Namen werden nie dupliziert. Beachten Sie, dass die Aufzählung eines Objekts über den Namensordner erheblich höher ist als das Aufrufen der IModelObject-Methoden.

EnumerateReferences

Die EnumerateReferences-Methode listet den Satz von Namen und Verweisen auf sie auf, die gemäß den Regeln der BindReference-Methode an das Objekt gebunden werden. Im Gegensatz zu den EnumerateKeys, EnumerateValues und ähnlichen Methoden für IModelObject, die mehrere Namen mit demselben Wert zurückgeben können (für Basisklassen, übergeordnete Modelle und ähnliches), gibt dieser Enumerationerator nur den spezifischen Satz von Namen zurück, der mit BindValue und BindReference gebunden wird. Namen werden nie dupliziert. Beachten Sie, dass die Aufzählung eines Objekts über den Namensordner erheblich höher ist als das Aufrufen der IModelObject-Methoden.

Debuggerdatenmodell-C++-Skriptdebuggingschnittstellen

Die Infrastruktur für Skriptanbieter im Datenmodell bietet auch ein Konzept zum Debuggen von Skripts. Jedes Skript, das Debugfunktionen für den Debughost verfügbar machen möchte, und die Debuggeranwendung, die das Datenmodell hostet, kann dies tun, indem debuggierbare Skripts zusätzlich zur IDataModelScriptDebug-Schnittstelle die IDataModelScript-Schnittstelle implementieren. Das Vorhandensein dieser Schnittstelle im Skript gibt an, dass sie für die Infrastruktur debuggierbar ist.

Während die IDataModelScriptDebug-Schnittstelle der Ausgangspunkt ist, um Zugriff auf die Debugfunktionen eines Skriptanbieters zu erhalten, wird sie von einer Reihe anderer Schnittstellen verbunden, um allgemeine Debugfunktionen bereitzustellen.

Die Debugschnittstellen sind:

Schnittstelle BESCHREIBUNG
IDataModelScriptDebug Die Kernschnittstelle, die ein Skriptanbieter bereitstellen muss, um ein Skript debuggen zu können. Die Implementierungsklasse der IDataModelScript-Schnittstelle muss QueryInterface für IDataModelScriptDebug verwenden, wenn das Skript debuggierbar ist.
IDataModelScriptDebugClient Die Benutzeroberfläche, die die Funktion des Skriptdebuggings bereitstellen möchte, implementiert die IDataModelScriptDebugClient-Schnittstelle. Der Skriptanbieter verwendet diese Schnittstelle, um Debuginformationen hin und her zu übergeben (z. B.: Ereignisse, die auftreten, Haltepunkte usw....)
IDataModelScriptDebugStack Der Skriptanbieter implementiert diese Schnittstelle, um den Begriff eines Aufrufstapels für den Skriptdebugger verfügbar zu machen.
IDataModelScriptDebugStackFrame Der Skriptanbieter implementiert diese Schnittstelle, um den Begriff eines bestimmten Stapelframes innerhalb des Aufrufstapels verfügbar zu machen.
IDataModelScriptDebugVariableSetEnumerator Der Skriptanbieter implementiert diese Schnittstelle, um eine Reihe von Variablen verfügbar zu machen. Dieser Satz kann den Satz von Parametern für eine Funktion, den Satz lokaler Variablen oder den Satz von Variablen innerhalb eines bestimmten Bereichs darstellen. Die genaue Bedeutung hängt davon ab, wie die Schnittstelle erworben wurde.
IDataModelScriptDebugBreakpoint Der Skriptanbieter implementiert diese Schnittstelle, um den Begriff und die Kontrolle eines bestimmten Haltepunkts innerhalb des Skripts verfügbar zu machen.
IDataModelScriptDebugBreakpointEnumerator Der Skriptanbieter implementiert dies, um alle Haltepunkte aufzulisten, die derzeit innerhalb des Skripts vorhanden sind (unabhängig davon, ob aktiviert oder nicht).

Die allgemeinen Verwaltungsschnittstellen sind:

Schnittstelle BESCHREIBUNG
IDataModelScriptProvider Die Kernschnittstelle, die ein Skriptanbieter implementieren muss. Dies ist die Schnittstelle, die beim Skript-Manager-Teil des Datenmodell-Managers registriert ist, um die Unterstützung eines bestimmten Skripttyps des Anbieters anzukündigen und sich bei einer bestimmten Dateierweiterung zu registrieren.
IDataModelScript Eine Abstraktion eines bestimmten Skripts, das vom Anbieter verwaltet wird. Jedes Skript, das geladen oder bearbeitet wird, verfügt über eine separate IDataModelScript-Instanz.
IDataModelScriptClient Eine Clientschnittstelle, die vom Skriptanbieter verwendet wird, um Informationen an eine Benutzeroberfläche zu übermitteln. Skriptanbieter implementieren diese Schnittstelle nicht. Die Anwendung, die das Datenmodell hosten soll, das Skriptanbieter verwenden möchte. Ein Skriptanbieter ruft Methoden des Skriptclients auf, um Status, Fehler usw. zu melden...
IDataModelScriptHostContext Eine Hostschnittstelle, die vom Skriptanbieter als Container für den Inhalt des Skripts verwendet wird. Wie der Inhalt einer anderen Skriptoberfläche als die Manipulationen, die sie für das Objektmodell der Debuggeranwendung ausführt, bis zum jeweiligen Debughost gehört. Diese Schnittstelle ermöglicht es dem Skriptanbieter, Informationen darüber abzurufen, wo der Inhalt platziert werden soll.
IDataModelScriptTemplate Skriptanbieter können eine oder mehrere Vorlagen bereitstellen, die als Ausgangspunkt für Benutzer zum Erstellen von Skripts dienen. Eine Debuggeranwendung, die einen integrierten Editor bereitstellt, kann neue Skripts mit Vorlageninhalten vorab ausfüllen, wie vom Anbieter über diese Schnittstelle angekündigt.
IDataModelScriptTemplateEnumerator Eine Enumerationsschnittstelle, die der Skriptanbieter implementiert, um alle unterstützten Vorlagen anzukündigen.
IDataModelNameBinder Ein Namensbinder - ein Objekt, das einen Namen in einem Kontext einem Wert zuordnen kann. Bei einem bestimmten Ausdruck wie "foo.bar" kann ein Namensbinder den Namen "bar" im Kontext des Objekts "foo" binden und einen Wert oder Einen Verweis darauf erzeugen. Namenmappen werden in der Regel nicht von einem Skriptanbieter implementiert. Stattdessen kann der Standardordner aus dem Datenmodell abgerufen und vom Skriptanbieter verwendet werden.

Erstellen von Skripts debuggierbar: IDataModelScriptDebug-

Jedes Skript, das debuggierbar ist, gibt diese Funktion über das Vorhandensein der IDataModelScriptDebug-Schnittstelle in derselben Komponente an, die IDataModelScript implementiert. Die Abfrage für diese Schnittstelle durch den Debughost oder die Debuggeranwendung, die das Datenmodell hosten, gibt das Vorhandensein der Debugfunktion an.

Die IDataModelScriptDebug-Schnittstelle wird wie folgt definiert.

DECLARE_INTERFACE_(IDataModelScriptDebug, IUnknown)
{
   STDMETHOD_(ScriptDebugState, GetDebugState)() PURE;
   STDMETHOD(GetCurrentPosition)(_Out_ ScriptDebugPosition *currentPosition, _Out_opt_ ScriptDebugPosition *positionSpanEnd, _Out_opt_ BSTR *lineText) PURE;
   STDMETHOD(GetStack)(_COM_Outptr_ IDataModelScriptDebugStack **stack) PURE;
   STDMETHOD(SetBreakpoint)(_In_ ULONG linePosition, _In_ ULONG columnPosition, _COM_Outptr_ IDataModelScriptDebugBreakpoint **breakpoint) PURE;
   STDMETHOD(FindBreakpointById)(_In_ ULONG64 breakpointId, _COM_Outptr_ IDataModelScriptDebugBreakpoint **breakpoint) PURE;
   STDMETHOD(EnumerateBreakpoints)(_COM_Outptr_ IDataModelScriptDebugBreakpointEnumerator **breakpointEnum) PURE;
   STDMETHOD(GetEventFilter)(_In_ ScriptDebugEventFilter eventFilter, _Out_ bool *isBreakEnabled) PURE;
   STDMETHOD(SetEventFilter)(_In_ ScriptDebugEventFilter eventFilter, _In_ bool isBreakEnabled) PURE;
   STDMETHOD(StartDebugging)(_In_ IDataModelScriptDebugClient *debugClient) PURE;
   STDMETHOD(StopDebugging)(_In_ IDataModelScriptDebugClient *debugClient) PURE;
}

GetDebugState-

Die GetDebugState-Methode gibt den aktuellen Status des Skripts zurück (z. B. ob es ausgeführt wird oder nicht). Der Zustand wird durch einen Wert innerhalb der ScriptDebugState-Aufzählung definiert.

GetCurrentPosition-

Die GetCurrentPosition'-Methode gibt die aktuelle Position innerhalb des Skripts zurück. Dies kann nur aufgerufen werden, wenn das Skript in den Debugger unterteilt wird, bei dem ein Aufruf von GetScriptState ScriptDebugBreak zurückgeben würde. Jeder andere Aufruf dieser Methode ist ungültig und schlägt fehl.

GetStack-

Die GetStack-Methode ruft den aktuellen Aufrufstapel an der Unterbrechungsposition ab. Diese Methode kann nur aufgerufen werden, wenn das Skript in den Debugger unterteilt ist.

SetBreakpoint-

Die SetBreakpoint-Methode legt einen Haltepunkt innerhalb des Skripts fest. Beachten Sie, dass die Implementierung frei ist, um die passierten Zeilen- und Spaltenpositionen so anzupassen, dass sie an eine geeignete Codeposition weitergeleitet werden. Die tatsächlichen Zeilen- und Spaltennummern, in denen der Haltepunkt platziert wurde, können von Methodenaufrufen auf der zurückgegebenen IDataModelScriptDebugBreakpoint-Schnittstelle abgerufen werden.

FindBreakpointById-

Jedem Haltepunkt, der über die SetBreakpoint-Methode innerhalb des Skripts erstellt wird, wird durch die Implementierung ein eindeutiger Bezeichner (eine 64-Bit-ganzzahl ohne Vorzeichen) zugewiesen. Die FindBreakpointById-Methode wird verwendet, um eine Schnittstelle zum Haltepunkt von einem bestimmten Bezeichner abzurufen.

EnumerateBreakpoints

Die EnumerateBreakpoints-Methode gibt einen Enumerator zurück, der jeden Haltepunkt aufzählt, der innerhalb eines bestimmten Skripts festgelegt wird.

GetEventFilter-

Die GetEventFilter-Methode gibt zurück, ob "Break on event" für ein bestimmtes Ereignis aktiviert ist. Ereignisse, die zu einem Unterbrechungsereignis führen können, werden von einem Mitglied der ScriptDebugEventFilter-Aufzählung beschrieben.

SetEventFilter-

Die SetEventFilter-Methode ändert das Verhalten "Break on event" für ein bestimmtes Ereignis, wie durch ein Element der ScriptDebugEventFilter-Aufzählung definiert. Eine vollständige Liste der verfügbaren Ereignisse (und eine Beschreibung dieser Enumeration) finden Sie in der Dokumentation für die GetEventFilter-Methode.

StartDebugging-

Die StartDebugging-Methode aktiviert den Debugger für ein bestimmtes Skript.The StartDebugging method "turns on" the debugger for a particular script. Der Vorgang des Startens des Debuggings führt nicht aktiv zu Ausführungsunterbrechungen oder Schrittschritten. Es macht das Skript lediglich debuggierbar und stellt eine Reihe von Schnittstellen bereit, über die der Client mit der Debugschnittstelle kommunizieren kann.

StopDebugging-

Die StopDebugging-Methode wird von einem Client aufgerufen, der das Debuggen beenden möchte. Dieser Methodenaufruf kann jederzeit erfolgen, nachdem StartDebugging erfolgreich durchgeführt wurde (z. B. während einer Unterbrechung, während der Ausführung des Skripts usw.). Der Aufruf beendet sofort alle Debugaktivitäten und setzt den Zustand zurück auf den StartDebugging-Aufruf.

debugschnittstelle: IDataModelScriptDebugClient

Der Debughost oder die Debuggeranwendung, die eine Schnittstelle zum Skriptdebugging bereitstellen möchte, muss eine Implementierung der IDataModelScriptDebugClient-Schnittstelle für den Skriptdebugger über die StartDebugging-Methode auf der Debugschnittstelle für das Skript bereitstellen.

Der IDataModelScriptDebugClient ist der Kommunikationskanal, über den Debugereignisse übergeben werden und die Steuerung vom Skriptausführungsmodul zu einer Debuggerschnittstelle wechselt. Es wird wie folgt definiert.

DECLARE_INTERFACE_(IDataModelScriptDebugClient, IUnknown)
{
   STDMETHOD(NotifyDebugEvent)(_In_ ScriptDebugEventInformation *pEventInfo, _In_ IDataModelScript *pScript, _In_opt_ IModelObject *pEventDataObject, _Inout_ ScriptExecutionKind *resumeEventKind) PURE;
}

NotifyDebugEvent-

Jedes Ereignis, das in den Skriptdebugger wechselt, ruft der Debugcode selbst über die NotifyDebugEvent-Methode die Schnittstelle auf. Diese Methode ist synchron. Es wird keine Ausführung des Skripts fortgesetzt, bis die Schnittstelle vom Ereignis zurückgegeben wird. Die Definition des Skriptdebuggers soll einfach sein: Es gibt absolut keine geschachtelten Ereignisse, die eine Verarbeitung erfordern. Ein Debugereignis wird durch einen Variant-Datensatz definiert, der als ScriptDebugEventInformation bezeichnet wird. Welche Felder in den Ereignisinformationen gültig sind, wird weitgehend vom DebugEvent-Element definiert. Es definiert die Art des Ereignisses, das durch ein Element der ScriptDebugEvent-Aufzählung beschrieben wurde.

Aufrufstapel: IDataModelScriptDebugStack

Wenn ein Ereignis auftritt, das in den Skriptdebugger wechselt, möchte die Debugschnittstelle den Aufrufstapel für den Unterbrechungsort abrufen. Dies erfolgt über die GetStack-Methode. Dieser Stapel wird über das IDataModelScriptDebugStack ausgedrückt, das wie unten angegeben definiert ist.

Beachten Sie, dass der Gesamtstapel mehrere Skripts und/oder mehrere Skriptanbieter umfassen kann. Der Aufrufstapel, der von einem einzelnen Aufruf der GetStack-Methode für die Debugschnittstelle eines bestimmten Skripts zurückgegeben wird, sollte nur das Segment des Aufrufstapels innerhalb der Grenzen dieses Skripts zurückgeben. Es ist völlig möglich, dass ein Skriptdebugmodul den Aufrufstapel abrufen kann, wenn zwei Skripts desselben Anbieters interagieren. Die GetStack-Methode sollte nicht den Teil des Stapels zurückgeben, der sich in einem anderen Skript befindet. Wenn diese Situation erkannt werden kann, sollte der Stapelframe, der den Begrenzungsrahmen in das Skript darstellt, über eine Implementierung der Methoden IsTransitionPoint und GetTransition in diesem Stapelframe als Übergangsframe kennzeichnen. Es wird erwartet, dass die Debuggerschnittstelle den Gesamtstapel aus den mehreren Stapelsegmenten zusammenfügt, die vorhanden sind.

Es ist zwingend erforderlich, dass Übergänge auf diese Weise implementiert werden, oder die Debugschnittstelle kann Anfragen zu lokalen Variablen, Parametern, Haltepunkten und anderen skriptspezifischen Konstrukten an den falschen Skriptkontext richten! Dies führt zu einem nicht definierten Verhalten in der Debuggerschnittstelle.

DECLARE_INTERFACE_(IDataModelScriptDebugStack, IUnknown)
{
   STDMETHOD_(ULONG64, GetFrameCount)() PURE;
   STDMETHOD(GetStackFrame)(_In_ ULONG64 frameNumber, _COM_Outptr_ IDataModelScriptDebugStackFrame **stackFrame) PURE;
}

GetFrameCount-

Die GetFrameCount-Methode gibt die Anzahl der Stapelframes in diesem Segment des Aufrufstapels zurück. Wenn der Anbieter Frames in unterschiedlichen Skriptkontexten oder von verschiedenen Anbietern erkennen kann, sollte er dies für den Aufrufer durch Implementierung der IsTransitionPoint- und GetTransition-Methoden für den Einstiegsrahmen in diesem Stapelsegment angeben.

GetStackFrame-

Der GetStackFrame ruft einen bestimmten Stapelframe aus dem Stapelsegment ab. Der Aufrufstapel verfügt über ein nullbasiertes Indizierungssystem: Der aktuelle Stapelframe, in dem das Unterbrechungsereignis aufgetreten ist, ist Frame 0. Der Aufrufer der aktuellen Methode ist Frame 1 (usw.).

Untersuchen des Zustands beim Fehlerhaften Überprüfen: IDataModelScriptDebugStackFrame

Ein bestimmter Frame des Aufrufstapels, wenn er in den Skriptdebugger unterteilt ist, kann über einen Aufruf der GetStackFrame-Methode auf der IDataModelScriptDebugStack-Schnittstelle abgerufen werden, die das Stapelsegment darstellt, in dem der Umbruch aufgetreten ist. Die IDataModelScriptDebugStackFrame-Schnittstelle, die zurückgegeben wird, um diesen Frame darzustellen, wird wie folgt definiert.

DECLARE_INTERFACE_(IDataModelScriptDebugStackFrame, IUnknown)
{
   STDMETHOD(GetName)(_Out_ BSTR *name) PURE;
   STDMETHOD(GetPosition)(_Out_ ScriptDebugPosition *position, _Out_opt_ ScriptDebugPosition *positionSpanEnd, _Out_opt_ BSTR *lineText) PURE;
   STDMETHOD(IsTransitionPoint)(_Out_ bool *isTransitionPoint) PURE;
   STDMETHOD(GetTransition)(_COM_Outptr_ IDataModelScript **transitionScript, _Out_ bool *isTransitionContiguous) PURE;
   STDMETHOD(Evaluate)(_In_ PCWSTR pwszExpression, _COM_Outptr_ IModelObject **ppResult) PURE;
   STDMETHOD(EnumerateLocals)(_COM_Outptr_ IDataModelScriptDebugVariableSetEnumerator **variablesEnum) PURE;
   STDMETHOD(EnumerateArguments)(_COM_Outptr_ IDataModelScriptDebugVariableSetEnumerator **variablesEnum) PURE;
}

GetName-

Die GetName-Methode gibt den Anzeigenamen (z. B. Funktionsname) dieses Frames zurück. Dieser Name wird innerhalb des Stapel-Backtrace angezeigt, der dem Benutzer in der Debuggerschnittstelle angezeigt wird.

GetPosition-

Die GetPosition-Methode gibt die Position innerhalb des Skripts zurück, das durch den Stapelrahmen dargestellt wird. Diese Methode kann nur aufgerufen werden, wenn sich das Skript innerhalb eines Durchbruchs befindet, der durch den Stapel dargestellt wird, in dem dieser Frame enthalten ist. Die Zeilen- und Spaltenposition innerhalb dieses Frames wird immer zurückgegeben. Wenn der Debugger die Spanne der "Ausführungsposition" innerhalb des Skripts zurückgeben kann, kann eine Endposition im argument positionSpanEnd zurückgegeben werden. Wenn der Debugger dies nicht unterstützt, sollten die Zeilen- und Spaltenwerte im Bereichsende (falls angefordert) auf Null festgelegt werden.

IsTransitionPoint-

Die IDataModelScriptDebugStack-Schnittstelle stellt ein Segment eines Aufrufstapels dar – dieser Teil des Aufrufstapels, der im Kontext eines Skripts enthalten ist. Wenn der Debugger in der Lage ist, den Übergang von einem Skript zu einem anderen (oder einem Skriptanbieter zu einem anderen) zu erkennen, kann er dies angeben, indem die IsTransitionPoint-Methode implementiert und je nach Bedarf "true" oder "false" zurückgegeben wird. Der Aufrufstapelframe, der das Skript eingegeben hat, in dem das Segment angewendet wird, sollte als Übergangspunkt betrachtet werden. Alle anderen Frames sind nicht.

GetTransition-

Wenn es sich bei einem bestimmten Stapelframe um einen Übergangspunkt handelt, der durch die IsTransition-Methode bestimmt wird (siehe dokumentation dort für eine Definition von Übergangspunkten), gibt die GetTransition-Methode Informationen über den Übergang zurück. Insbesondere gibt diese Methode das vorherige Skript zurück – das Skript, das einen Aufruf des Skripts vorgenommen hat, das durch das Stapelsegment dargestellt wird, das diesen IDataModelScriptDebugStackFrame enthält.

auswerten

Die Evaluate-Methode wertet einen Ausdruck (der Sprache des Skriptanbieters) im Kontext des Stapelframes aus, der durch die IDataModelScriptDebugStackFrame-Schnittstelle dargestellt wird, auf der diese Methode aufgerufen wurde. Das Ergebnis der Ausdrucksauswertung muss vom Skriptanbieter als IModelObject gemarstet werden. Die Eigenschaften und andere Konstrukte für das resultierende IModelObject müssen alle abgerufen werden können, während sich der Debugger im Unterbrechungszustand befindet.

EnumerateLocals

Die EnumerateLocals-Methode gibt einen Variablensatz (dargestellt durch eine IDataModelScriptDebugVariableSetEnumerator-Schnittstelle) für alle lokalen Variablen zurück, die sich im Kontext des Stapelframes befinden, der durch die IDataModelScriptDebugStackFrame-Schnittstelle dargestellt wird, auf der diese Methode aufgerufen wurde.

EnumerateArguments

Die EnumerateArguments-Methode gibt einen Variablensatz (dargestellt durch eine IDataModelScriptDebugVariableSetEnumerator-Schnittstelle) für alle Funktionsargumente der Funktion zurück, die im Stapelframe aufgerufen wird, dargestellt durch die IDataModelScriptDebugStackFrame-Schnittstelle, auf der diese Methode aufgerufen wurde.

Betrachten von Variablen: IDataModelScriptDebugVariableSetEnumerator

Eine Gruppe von Variablen in dem Skript, das gedebuggt wird (unabhängig davon, ob diese in einem bestimmten Bereich, die Gebietsschemas einer Funktion, die Argumente einer Funktion usw.) durch einen Variablensatz dargestellt werden, der über die IDataModelScriptDebugVariableSetEnumerator-Schnittstelle definiert ist:

DECLARE_INTERFACE_(IDataModelScriptDebugVariableSetEnumerator, IUnknown)
{
    STDMETHOD(Reset)() PURE;
    STDMETHOD(GetNext)(_Out_ BSTR *variableName, _COM_Outptr_opt_ IModelObject **variableValue, _COM_Outptr_opt_result_maybenull_ IKeyStore **variableMetadata) PURE;
}

zurücksetzen

Mit der Reset-Methode wird die Position des Enumerators an die Stelle zurückgesetzt, an der sie unmittelbar nach der Erstellung lag – d. h. vor dem ersten Element des Satzes.

GetNext-

Die GetNext-Methode verschiebt den Enumerator in die nächste Variable im Satz und gibt den Namen, den Wert und alle damit verbundenen Metadaten zurück. Wenn der Enumerator das Ende des Satzes erreicht hat, wird der Fehler zurückgegeben, E_BOUNDS zurückgegeben wird. Sobald die E_BOUNDS Markierung von der GetNext-Methode zurückgegeben wurde, wird weiterhin E_BOUNDS erzeugt, wenn der Aufruf erneut aufgerufen wird, es sei denn, ein dazwischen liegender Reset-Aufruf wird ausgeführt.

Haltepunkte: IDataModelScriptDebugBreakpoint

Skript-Haltepunkte werden über die SetBreakpoint-Methode auf der Debugschnittstelle eines bestimmten Skripts festgelegt. Solche Haltepunkte werden sowohl durch eine eindeutige ID als auch durch eine Implementierung der IDataModelScriptDebugBreakpoint-Schnittstelle dargestellt, die wie folgt definiert ist.

DECLARE_INTERFACE_(IDataModelScriptDebugBreakpoint, IUnknown)
{
    STDMETHOD_(ULONG64, GetId)() PURE;
    STDMETHOD_(bool, IsEnabled)() PURE;
    STDMETHOD_(void, Enable)() PURE;
    STDMETHOD_(void, Disable)() PURE;
    STDMETHOD_(void, Remove)() PURE;
    STDMETHOD(GetPosition)(_Out_ ScriptDebugPosition *position, _Out_opt_ ScriptDebugPosition *positionSpanEnd, _Out_opt_ BSTR *lineText) PURE;
}

GetId-

Die GetId-Methode gibt den eindeutigen Bezeichner zurück, der vom Debugmodul des Skriptanbieters dem Haltepunkt zugewiesen wurde. Dieser Bezeichner muss im Kontext des enthaltenden Skripts eindeutig sein. Der Haltepunktbezeichner kann für den Anbieter eindeutig sein; Das ist jedoch nicht erforderlich.

IsEnabled

Die IsEnabled-Methode gibt zurück, ob der Haltepunkt aktiviert ist. Ein deaktivierter Haltepunkt ist weiterhin vorhanden und befindet sich noch in der Liste der Haltepunkte für das Skript, es ist lediglich vorübergehend "deaktiviert". Alle Haltepunkte sollten im aktivierten Zustand erstellt werden.

Aktivieren

Die Enable-Methode aktiviert den Haltepunkt. Wenn der Haltepunkt deaktiviert wurde, führt das "Drücken des Haltepunkts" nach dem Aufrufen dieser Methode zu einem Bruch in den Debugger.

Deaktivieren

Die Disable-Methode deaktiviert den Haltepunkt. Nach diesem Aufruf wird das "Drücken des Haltepunkts" nach dem Aufrufen dieser Methode nicht in den Debugger unterteilt. Der Haltepunkt, während er noch vorhanden ist, wird als "deaktiviert" betrachtet.

entfernen

Die Remove-Methode entfernt den Haltepunkt aus der enthaltenden Liste. Der Haltepunkt ist nach dem Zurückgeben dieser Methode nicht mehr semantisch vorhanden. Die IDataModelScriptDebugBreakpoint-Schnittstelle, die den Haltepunkt darstellt, wird nach dem Aufruf als verwaist betrachtet. Nichts anderes kann (rechtlich) nach diesem Aufruf erfolgen, außer es freizugeben.

GetPosition-

Die GetPosition-Methode gibt die Position des Haltepunkts innerhalb des Skripts zurück. Der Skriptdebugger muss die Zeile und Spalte im Quellcode zurückgeben, in der sich der Haltepunkt befindet. Wenn dies möglich ist, kann sie auch eine durch den Haltepunkt dargestellte Quellspanne zurückgeben, indem sie eine Endposition ausfüllt, die durch das argument positionSpanEnd definiert ist. Wenn der Debugger diese Spanne nicht produzieren kann und der Aufrufer sie anfordert, sollten die Zeilen- und Spaltenfelder der Endposition der Spanne als Null ausgefüllt werden, die angibt, dass die Werte nicht angegeben werden können.

Breakpoint-Aufzählung: IDataModelScriptDebugBreakpointEnumerator

Wenn ein Skriptanbieter das Debuggen unterstützt, muss er auch alle Haltepunkte nachverfolgen, die jedem und jedem Skript zugeordnet sind, und diese Haltepunkte auf der Debugschnittstelle aufzählen können. Der Enumerator für Haltepunkte wird über die EnumerateBreakpoints-Methode auf der Debugschnittstelle für ein bestimmtes Skript abgerufen und wie folgt definiert.

DECLARE_INTERFACE_(IDataModelScriptDebugBreakpointEnumerator, IUnknown)
{
   STDMETHOD(Reset)() PURE;
   STDMETHOD(GetNext)(_COM_Outptr_ IDataModelScriptDebugBreakpoint **breakpoint) PURE;
}

zurücksetzen

Mit der Reset-Methode wird die Position des Enumerators an die Stelle zurückgesetzt, an der sie unmittelbar nach der Erstellung des Enumerationsgebers lag , d. h. vor dem ersten aufgezählten Haltepunkt.

GetNext-

Die GetNext-Methode verschiebt den Enumerator vorwärts an den nächsten Haltepunkt, der aufgezählt werden soll, und gibt die IDataModelScriptDebugBreakpoint-Schnittstelle für diesen Haltepunkt zurück. Wenn der Enumerator das Ende der Enumeration erreicht hat, wird E_BOUNDS zurückgegeben. Nachdem der E_BOUNDS Fehler erzeugt wurde, werden nachfolgende Aufrufe der GetNext-Methode weiterhin E_BOUNDS erzeugt, es sei denn, ein dazwischen liegender Aufruf der Reset-Methode wurde ausgeführt.


Siehe auch

Dieses Thema ist Teil einer Reihe, in der die von C++ zugänglichen Schnittstellen beschrieben werden, wie sie zum Erstellen einer C++-basierten Debuggererweiterung und zur Verwendung anderer Datenmodellkonstrukte (z. B. JavaScript oder NatVis) aus einer C++-Datenmodellerweiterung verwendet werden.

Debuggerdatenmodell C++-Übersicht

Debuggerdatenmodell-C++-Schnittstellen

Debugger-Datenmodell-C++-Objekte

Debuggerdatenmodell C++ zusätzliche Schnittstellen

Debuggerdatenmodell-C++-Konzepte