ComObjActive() [AHK_L 53+]

Ermittelt ein laufendes Objekt, das mit OLE registriert wurde.

ComObject := ComObjActive(CLSID)

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

ParamObj := ComObject(VarTyp, Wert , Flags)

Veraltet: Die unten gezeigten Verwendungen sind veraltet und werden in einer zukünftigen Version geändert oder nicht mehr zur Verfügung stehen.

Erstellt ein Objekt, das stellvertretend für den Standardwert eines optionalen Parameters verwendet werden kann, wenn eine Methode eines COM-Objekts aufgerufen wird. [v1.1.12+]: Diese Funktion ist veraltet. Schreiben Sie stattdessen zwei aufeinanderfolgende Kommas, wie z. B. in Obj.Methode(1,,3)

ParamObj := ComObjMissing()

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

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

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

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

Parameter

CLSID

CLSID oder eine visuell lesbare ProgID des COM-Objekts.

ComObject

COM-Objekt, das mit der Objekt-Syntax verwendbar ist.

VarTyp

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

Wert

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

Flags

Flags haben Einfluss auf das Verhalten dieser Funktion und des Wrapper-Objekts (siehe unten).

DispPtr

Roher IDispatch-Pointer.

Flags

Flag Auswirkung
0

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

Da das Standardverhalten in einer zukünftigen Version eventuell geändert wird, ist es ratsam, Flags immer auf 1 zu setzen, wenn ein Interface-Pointer gewrappt wird, und ObjAddRef() aufzurufen, falls nötig.

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

ByRef [v1.1.17+]

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

Beim Erstellen einer Referenz muss Wert die Speicheradresse einer Variable oder eines Pufferspeichers mit genügend Kapazität sein, um einen Wert bestimmten Typs enthalten zu können. 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 zwar jeder vorherige Wert freigegeben wird, wenn ein neuer Wert mittels vref[] oder der COM-Methode zugewiesen wird, aber der finale Wert nicht automatisch freigegeben wird. Für die Freigabe des Wertes muss man wissen, um welchen Typ es sich handelt. Da es sich in diesem Fall um VT_VARIANT handelt, kann es durch Aufrufen von VariantClear mit DllCall oder durch Verwendung einer einfacheren Methode freigegeben werden: weisen Sie einen Integer zu, z. B. vref[] := 0.

Allgemeine Bemerkungen

In den aktuellen Versionen wird jeder Funktionsaufruf, der mit "ComObj" beginnt, aber keine der internen COM-Funktionen 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 ein aktives Objekt nicht abrufen kann, wird die Funktion je nach aktueller ComObjError()-Einstellung und anderen Faktoren eventuell eine Ausnahme auslösen, das Skript beenden oder eine leere Zeichenkette zurückgeben.

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

Bekannte Einschränkung: Jedes Mal, wenn ein COM-Objekt gewrappt wird, wird ein neues Wrapper-Objekt erstellt. Bei Vergleichen und Zuweisungen wie if (obj1 == obj2) und array[obj1] := Wert werden beide Wrapper-Objekte nicht als identisch angesehen, obwohl sie das gleiche COM-Objekt enthalten.

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

Beispiele

ComObjUnwrap: Siehe ComObjConnect().

Übergibt 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: 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.

; Das Gleiche 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 via ByRef übergeben werden kann.
;   ComVar[] bekommt den Wert.
;   ComVar[] := Val setzt den Wert.
;   ComVar.ref bekommt ein ByRef-Objekt, das eine COM-Funktion nutzen kann.
ComVar(Type := 0xC)
{
    static base := { __Get: Func("ComVarGet"), __Set: Func("ComVarSet")
        , __Delete: Func("ComVarDel") } ; Näheres zu base finden Sie unter Benutzerdefinierte Objekte.
    
    ; Neues Objekt basierend auf base erstellen.
    cv := {base: base}
    
    ; Speicher für ein VARIANT reservieren, damit unser Wert reinpasst. 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 via 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 dies erforderlich sein, um den Wert freizugeben, sofern gesetzt.
    DllCall("oleaut32\VariantClear", "ptr", cv.GetAddress("buf"))
}