Manchmal muss unsere COM-Komponente eine Benachrichtigung an den Client senden oder die Rückruffunktion aufrufen. Das Schema ist einfach: Die Komponente veröffentlicht die Schnittstelle, der Client erstellt ein von der Schnittstelle geerbtes Objekt und übergibt es an die Komponente. Die Komponente ruft wiederum die Schnittstellenfunktionen auf und ruft damit die Funktionen auf der Clientseite auf.
Im Fall von Visual Basic oder Visual Basic für Anwendungen können wir eine Klasse schreiben, die von einer beliebigen Schnittstelle geerbt wurde. Dies ist jedoch für VBScript-Skriptdateien nicht möglich.
Hier eilt uns die IDispatch
Schnittstelle zu Hilfe. Über diese Schnittstelle übernimmt unsere leistungsstarke Komponente demütig die bescheidene Rolle eines Clients, und aus einem kleinen Skript wird ein echter Automatisierungsserver.
Wir werden die Komponente in der Programmiersprache FreeBASIC entwickeln.
Klassen in der Skriptdatei
Sie können Klassen in Skriptdateien deklarieren und verwenden. Solche Klassen werden implizit von der IDispatch
Schnittstelle geerbt und sind echte COM-Klassen.
Wir deklarieren eine Klasse, deren Instanz wir anschließend an unsere Komponente übergeben werden:
Class CallBack Function CallBack(Param)
Unsere Komponente empfängt eine Instanz der CallBack
Klasse, ruft die CallBack
Funktion auf und CallBack
ihr eine Zeichenfolge mit Text im Parameter.
IDispatch
Diese Schnittstelle ist der Stolperstein der Automatisierung. Normalerweise basiert die Implementierung von IDispatch
auf einer ITypeInfo->Invoke
über ITypeInfo->Invoke
oder die Funktion CreateStdDispatch
In diesem Fall befindet sich der Automatisierungsserver jedoch in einem Skript und verfügt nicht über eine CreateStdDispatch
Unsere Komponente fungiert als Client. Zur Vereinfachung funktioniert IDipatch
: IDipatch
den Namen der Funktion und überträgt die Kontrolle an sie.
Die Definition der Schnittstelle liegt in der Überschrift „oaidl.bi“ (Einrückungen und Zeilenumbrüche werden zur besseren Lesbarkeit hinzugefügt):
Type IDispatch As IDispatch_ Type LPDISPATCH As IDispatch Ptr Type IDispatchVtbl
Die Funktionen GetIDsOfNames
und Invoke
sind in dieser Schnittstelle am interessantesten.
GetIDsOfNames
Es nimmt den Namen der Funktion und gibt ihre DISPID
. DISPID
ist ein Alias für den Typ LONG
.
Aus Sicht des DISPID
ist DISPID
lediglich ein Optimierungswerkzeug, das das Übergeben von Zeichenfolgen vermeidet. Für den Server ist DISPID
die Kennung der Funktion, die der Client aufrufen möchte.
Rufen Sie auf
Per Versand führt die Kennung die entsprechende Funktion aus.
DISPPARAMS
Diese Struktur enthält die Parameter der aufgerufenen Funktion. Alle Parameter sind in VARIANT
.
Type tagDISPPARAMS
Um den Code zu vereinfachen, verwenden wir keine benannten Argumente, sondern setzen stattdessen NULL
.
Komponente
Für die Verwendung in Skripten sollten Komponenten auch direkt oder indirekt von IDipatch
erben.
ITestCOMServer-Schnittstelle
Erstellen ITestCOMServer
die ITestCOMServer
Schnittstelle mit zwei Funktionen, SetCallBack
und InvokeCallBack
. Der erste speichert das Automatisierungsserverobjekt, der zweite ruft die Objektfunktion auf.
Type ITestCOMServer As ITestCOMServer_ Type LPITESTCOMSERVER As ITestCOMServer Ptr Type ITestCOMServerVirtualTable
Klasse TestCOMServer
Jetzt können Sie eine COM-Klasse deklarieren:
Type TestCOMServer
Funktionsrückruf
Die Implementierung der SetCallBack
Funktion SetCallBack
einfach: Wir speichern das vom Client übertragene Automatisierungsserverobjekt und den Funktionsaufrufparameter.
Function TestCOMServerSetCallBack( _ ByVal pTestCOMServer As TestCOMServer Ptr, _ ByVal CallBack As IDispatch Ptr, _ ByVal UserName As BSTR _ )As HRESULT
InvokeCallBack-Funktion
Die InvokeCallBack
Funktion InvokeCallBack
jedoch hart arbeiten. Zuerst müssen Sie die Dispatcher- CallBack
der CallBack
Funktion des Automatisierungsservers CallBack
.
Function TestCOMServerInvokeCallBack( _ ByVal pTestCOMServer As TestCOMServer Ptr _ )As HRESULT If pTestCOMServer->CallBack = NULL Then Return E_POINTER End If
Nachdem die DISPID
Funktion empfangen wurde, kann sie aufgerufen werden:
Fazit
Wie Sie sehen, kann eine Komponente auch mit einer Skriptdatei Feedback erhalten. Dies ist nützlich, um den Client über abgeschlossene Vorgänge durch die Komponente zu informieren.
Klassen in Skripten können in der Registrierung registriert werden. In diesem Fall sind sie mit ProgID
für das gesamte System ProgID
. Dies ist jedoch eine ganz andere Geschichte.
Referenzen
Projektcode auf der Github-Site: https://github.com/zamabuvaraeu/TestCOMServer
PS Irgendwie verschwand das Highlight für die BASIC-Syntax, stattdessen wurde VBScript verwendet, und einige Operatoren werden damit nicht hervorgehoben.