ComObjActive() und Verwandte [AHK_L 53+]

Inhaltsverzeichnis

ComObjActive()

Ruft ein laufendes Objekt ab, das mit OLE registriert wurde.

ComObject := ComObjActive(CLSID)

Parameter

CLSID

CLSID oder eine visuell lesbare ProgID des COM-Objekts.

Rückgabewert

Diese Funktion gibt ein neues COM-Wrapper-Objekt mit dem Variantentyp VT_DISPATCH (9) zurück.

ComObject()

Erstellt ein Objekt, das in typisierter Form als Parameter oder Rückgabewert übergeben werden kann.

ParamObj := ComObject(VarTyp, Wert , Flags)

Parameter

VarTyp

Ein Integer, der den Typ des Wertes angibt. Eine Auflistung aller Typennummern finden Sie unter ComObjType().

Wert

Ein Wert, der gewrappt werden soll. Derzeit werden nur Integer und Pointer-Werte unterstützt.

Flags

Flags haben Einfluss auf das Verhalten dieser Funktion und des Wrapper-Objekts; siehe die Tabelle unten.

Rückgabewert

Diese Funktion gibt ein Wrapper-Objekt zurück, das einen Variantentyp und einen Wert oder Pointer enthält.

Flags

Flag Effekt
0

Standardverhalten. AddRef() wird automatisch für IUnknown- und IDispatch-Pointer aufgerufen, daher sollte der Aufrufer ObjRelease() verwenden, um ihre Kopie des Pointers freizugeben, falls erforderlich.

Da das Standardverhalten in einer zukünftigen Version geändert werden könnte, ist es ratsam, Flags beim Wrappen eines Interface-Pointers immer auf 1 zu setzen und ObjAddRef() bei Bedarf aufzurufen.

1 Ergreift Besitz von einem IUnknown-, IDispatch- oder SAFEARRAY-Pointer. AddRef wird nicht aufgerufen. Wenn das Wrapper-Objekt einen SAFEARRAY (außer VT_BYREF) enthält, wird beim Freigeben des Wrapper-Objekts automatisch SafeArrayDestroy aufgerufen.

ByRef [v1.1.17+]

Wenn der VarTyp eines Wrapper-Objekts das VT_BYREF-Flag (0x4000) enthält, können leere eckige Klammern [] zum Lesen oder Schreiben des referenzierten Wertes verwendet werden.

Beim Erstellen einer Referenz muss Wert die Speicheradresse einer Variable oder eines Pufferspeichers mit ausreichender Kapazität zur Aufbewahrung eines Wertes bestimmten Typs sein. Das folgende Beispiel erstellt eine Variable, die von einer VBScript-Funktion beschrieben werden kann:

VarSetCapacity(var, 24, 0)
vref := ComObject(0x400C, &var)  ; 0x400C ist eine Kombination von VT_BYREF und VT_VARIANT.

vref[] := "Eingabewert"
sc.Run("Beispiel", vref)  ; sc sollte wie im Beispiel unten initialisiert werden.
MsgBox % vref[]

Beachten Sie, dass, obwohl alle vorherigen Werte freigegeben werden, wenn ein neuer Wert mittels vref[] oder der COM-Methode zugewiesen wird, der finale Wert nicht automatisch freigegeben wird. Um den Wert freizugeben, muss man wissen, um welchen Typ es sich handelt. Da es sich in diesem Fall um VT_VARIANT handelt, kann der Wert durch Aufruf von VariantClear mit DllCall oder durch Nutzung einer einfacheren Methode freigegeben werden: weisen Sie einen Integer zu, z.B. vref[] := 0.

ComObjParameter()

Veraltet: Diese Funktion ist nicht für neue Skripte empfohlen. Verwenden Sie stattdessen ComObject().

Erstellt ein Objekt, das in typisierter Form als Parameter übergeben werden kann.

ParamObj := ComObjParameter(VarTyp, Wert , Flags)

Einzelheiten finden Sie unter ComObject() oben.

ComObjMissing()

[v1.1.12+] Veraltet: Diese Funktion ist nicht für neue Skripte empfohlen. Schreiben Sie stattdessen zwei aufeinanderfolgende Kommas, wie in Obj.Methode(1,,3).

Erstellt ein Objekt, das als Ersatz für den Standardwert eines optionalen Parameters beim Aufruf einer Methode eines COM-Objekts verwendet werden kann.

ParamObj := ComObjMissing()

Rückgabewert

Diese Funktion gibt ein Wrapper-Objekt mit dem Variantentyp VT_ERROR (0xA) zurück.

ComObjEnwrap() / ComObjUnwrap()

Veraltet: Diese Funktionen sind nicht für neue Skripte empfohlen. Siehe Bemerkungen unten.

Wrappt oder entwrappt einen rohen IDispatch-Pointer in ein brauchbares Objekt und ruft automatisch AddRef auf.

ComObject := ComObjEnwrap(DispPtr)
DispPtr := ComObjUnwrap(ComObject)

Parameter

ComObject

COM-Objekt, das mit der Objektsyntax verwendet werden kann.

DispPtr

Roher IDispatch-Pointer.

Rückgabewert

ComObjEnwrap gibt ein COM-Objekt zurück, das mit der Objektsyntax verwendet werden kann. ComObjUnwrap gibt einen rohen IDispatch-Pointer zurück.

Bemerkungen

Um den Code zukunftssicherer zu machen, können Sie stattdessen Folgendes verwenden:

ComObject := ComObject(9, DispPtr, 1), ObjAddRef(DispPtr)
DispPtr := ComObjValue(ComObject), ObjAddRef(DispPtr)

Ein Beispiel dazu finden Sie unter ComObjConnect().

Allgemeine Bemerkungen

In den aktuellen Versionen wird jeder Funktionsaufruf, der mit "ComObj" beginnt, aber keine interne COM-Funktion ist, tatsächlich ComObjActive aufrufen. Zum Beispiel sind ComObjEnwrap(DispPtr) und ComObjActive(DispPtr) beide äquivalent zu ComObject(DispPtr) (standardmäßig mit VarTyp 9). Allerdings wird dieses Verhalten in einer zukünftigen Version nicht mehr verfügbar sein, so dass es am besten ist, nur ComObject() und ComObjActive() zu verwenden, wie auf dieser Seite gezeigt.

Wenn ComObjActive nicht in der Lage ist, ein aktives Objekt abzurufen, kann die Funktion eine Ausnahme auslösen, das Skript beenden oder eine leere Zeichenkette zurückgeben, abhängig von der aktuellen ComObjError()-Einstellung und anderen Faktoren.

Wenn diese Funktion verwendet wird, um einen IDispatch- oder IUnknown-Interface-Pointer zu wrappen oder abzurufen, wird die Referenzanzahl des COM-Objekts standardmäßig um 1 erhöht. Daher muss der Interface-Pointer manuell freigegeben werden, wenn er nicht mehr benötigt wird. Beim Freigeben des Wrapper-Objekts wird die darin enthaltene Referenz automatisch freigegeben.

Bekannte Einschränkung: Jedes Mal, wenn ein COM-Objekt gewrappt wird, wird ein neues Wrapper-Objekt erstellt. Vergleiche und Zuweisungen wie if (obj1 == obj2) und array[obj1] := Wert behandeln die beiden Wrapper-Objekte als nicht identisch, auch wenn sie dasselbe COM-Objekt enthalten.

ComObjCreate(), ComObjGet(), ComObjConnect(), ComObjError(), ComObjFlags(), ObjAddRef() / ObjRelease(), ComObjQuery(), GetActiveObject (Microsoft Docs)

Beispiele

Übergibt eine VARIANT ByRef an eine COM-Funktion.

; Einleitung - ScriptControl benötigt eine 32-Bit-Version von AutoHotkey.
code =
(
Sub Beispiel(Var)
    MsgBox Var
    Var = "Ausgabewert!"
End Sub
)
sc := ComObjCreate("ScriptControl"), sc.Language := "VBScript", sc.AddCode(code)


; Beispiel: Eine VARIANT ByRef an eine COM-Funktion übergeben.
var := ComVar()
var[] := "Eingabewert"  ; Mit [] einen Wert zuweisen.
sc.Run("Beispiel", var.ref)  ; VT_BYREF ComObject übergeben (.ref).
MsgBox % var[]  ; Mit [] einen Wert abrufen.

; Dasselbe noch einmal, aber direkter:
VarSetCapacity(variant_buf, 24, 0)  ; Einen Puffer anlegen, der groß genug für ein VARIANT ist.
var := ComObject(0x400C, &variant_buf)  ; Referenz auf ein VARIANT machen.
var[] := "Eingabewert"
sc.Run("Beispiel", var)  ; VT_BYREF ComObject selbst übergeben, kein [] oder .ref.
MsgBox % var[]
; Wenn ein VARIANT eine Zeichenkette oder ein Objekt enthält, muss es explizit freigegeben
; werden, indem VariantClear aufgerufen oder ein rein numerischer Wert zugewiesen wird:
var[] := 0


; ComVar: Erstellt ein Objekt, mit dem ein Wert ByRef übergeben werden kann.
;   ComVar[] ruft den Wert ab.
;   ComVar[] := Val setzt den Wert.
;   ComVar.ref ruft ein ByRef-Objekt zur Übergabe an eine COM-Funktion ab.
ComVar(Type := 0xC)
{
    static base := { __Get: Func("ComVarGet"), __Set: Func("ComVarSet")
        , __Delete: Func("ComVarDel") } ; Für base siehe Benutzerdefinierte Objekte.
    
    ; Neues Objekt basierend auf base erstellen.
    cv := {base: base}
    
    ; Speicher für ein VARIANT reservieren, damit unser Wert hineinpasst. VARIANT wird auch dann
    ; verwendet, wenn Type != VT_VARIANT, damit VariantClear von __delete verwendet werden kann.
    cv.SetCapacity("buf", 24), ptr := cv.GetAddress("buf")
    NumPut(0, NumPut(0, ptr+0, "int64"), "int64")
    
    if (Type != 0xC) { ; Kein VT_VARIANT.
        NumPut(Type, ptr+0, "ushort") ; Variantentyp für __delete setzen.
        ptr += 8 ; Auf den tatsächlichen Wert verweisen.
    }
    
    ; Ein Objekt erstellen, mit dem die Variable ByRef übergeben werden kann.
    cv.ref := ComObject(0x4000|Type, ptr)
    
    return cv
}

ComVarGet(cv, p*) { ; Wird aufgerufen, wenn das Skript auf ein unbekanntes Feld zugreift.
    if p.MaxIndex() = "" ; Keine Namen/Parameter, also cv[]
        return cv.ref[]
}

ComVarSet(cv, v, p*) { ; Wird aufgerufen, wenn das Skript ein unbekanntes Feld setzt.
    if p.MaxIndex() = "" ; Keine Namen/Parameter, also cv[]:=v
        return cv.ref[] := v
}

ComVarDel(cv) { ; Wird aufgerufen, wenn das Objekt freigegeben wird.
    ; Je nach Typ kann das notwendig sein, um den Wert freizugeben, falls gesetzt.
    DllCall("oleaut32\VariantClear", "ptr", cv.GetAddress("buf"))
}