ComObject

Wraps a value, SafeArray or COM object for use by the script or for passing to a COM method.

ComObject := ComObject(VarType, Value , Flags)

Advanced: Wraps or unwraps a raw IDispatch pointer for use by the script.

ComObject := ComObject(DispPtr)

Parameters

VarType

Type: Integer

An integer indicating the type of value. See ComObjType for a list of types.

Value

Type: Integer

The value to wrap. Currently only integer and pointer values are supported.

Flags

Type: Integer

Flags affecting the behaviour of the wrapper object; see ComObjFlags for details.

DispPtr

Type: Integer

Raw IDispatch pointer.

Return Value

Type: Object

Returns a wrapper object containing a variant type and value or pointer.

This object has two uses:

  1. Some COM methods may require specific types of values which have no direct equivalent within AutoHotkey. This function allows the type of a value to be specified when passing it to a COM method. For example, ComObject(0xB, -1) creates an object which represents the COM boolean value true.
  2. Wrapping a COM object or SafeArray enables the script to interact with it more naturally, using object syntax. However, the majority of scripts do not need to do this manually since a wrapper object is created automatically by ComObjCreate, ComObjArray and any COM method which returns an object.

Ptr

If a wrapper object's VarType is VT_UNKNOWN (13) or includes the VT_BYREF (0x4000) flag or VT_ARRAY (0x2000) flag, the Ptr property can be used to retrieve the address of the object, typed variable or SafeArray. This allows the ComObject itself to be passed to any DllCall parameter which has the "Ptr" type, but can also be used explicitly. For example, ComObj.Ptr is equivalent to ComObjValue(ComObj) in these cases.

ByRef

If a wrapper object's VarType includes the VT_BYREF (0x4000) flag, empty brackets [] can be used to read or write the referenced value.

When creating a reference, Value must be the memory address of a variable or buffer with sufficient capacity to store a value of the given type. For example, the following can be used to create a variable which a VBScript function can write into:

VarSetCapacity(var, 24, 0)
vref := ComObject(0x400C, &var)  ; 0x400C is a combination of VT_BYREF and VT_VARIANT.

vref[] := "in value"
sc.Run("Example", vref)  ; sc should be initialized as in the example below.
MsgBox vref[]

General Remarks

When this function is used to wrap an IDispatch or IUnknown interface pointer, the wrapper object assumes responsibility for automatically releasing the pointer when appropriate. If VarType was omitted, the object is queried for its IDispatch interface; if one is returned, DispPtr is immediately released. Therefore, if the script intends to use the pointer after calling this function, it must call ObjAddRef(DispPtr) first.

The VarType of a wrapper object can be retrieved using ComObjType.

The Value of a wrapper object can be retrieved using ComObjValue.

Known limitation: Each time a COM object is wrapped, a new wrapper object is created. Comparisons and assignments such as obj1 == obj2 and array[obj1] := value treat the two wrapper objects as unique, even though they contain the same COM object.

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

Examples

#1

; Preamble - ScriptControl requires a 32-bit version of AutoHotkey.
code := "
(
Sub Example(Var)
    MsgBox Var
    Var = "out value!"
End Sub
)"
sc := ComObjCreate("ScriptControl"), sc.Language := "VBScript", sc.AddCode(code)


; Example: Pass a VARIANT ByRef to a COM method.
var := ComVar.new()
var[] := "in value"
sc.Run("Example", var.ref)
MsgBox var[]


; ComVar: An object which can be used to pass a value ByRef.
;   this[] retrieves the value.
;   this[] := Val sets the value.
;   this.ref retrieves a ByRef object for passing to a COM method.
class ComVar {
    __new(Type := 0xC) {
        ; Allocate memory for the typed variable.
        ; The largest supported type is VT_VARIANT on x64 (24 bytes).
        this.var := BufferAlloc(24, 0)
        ; Create an object which can be used to pass the variable ByRef.
        this.ref := ComObject(0x4000|Type, this.var.ptr + (Type=0xC ? 0 : 8))
    }
    __item {
        get => this.ref[]
        set => this.ref[] := value
    }
}