# ComObjQuery() [v1.0.96.00+]

查询 COM 对象的接口或服务.

    InterfacePointer := ComObjQuery(ComObject, SID, IID)

## 参数

ComObject

  COM 包装器对象或原始接口指针.

IID

  格式为 "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" 的接口标识符(GUID).

SID

  与 IID 格式相同的服务标识符. 省略此参数时, 必须同时省略后面跟着的逗号.

## 一般说明

在此函数使用两个参数时, 它相当于 IUnknown::QueryInterface. 如果同时指定了 SID 和 IID, 那么它会内部查询 IServiceProvider 接口, 然后调用 IServiceProvider::QueryService. 在两种形式中, 返回值为零或到被请求接口的指针. 通常在脚本结束时必须释放这种指针.

## 相关

ObjRelease(), ComObjCreate(), ComObjGet(), ComObjActive(), ComObjError()

## 示例

确定对象的类名.

    obj := ComObjCreate("Scripting.Dictionary")

    MsgBox % "Interface name: " ComObjType(obj, "name")

    IID_IProvideClassInfo := "{B196B283-BAB4-101A-B69C-00AA00341D07}"

    ; 请求到对象的 IProvideClassInfo 接口的指针.
    if !(pci := ComObjQuery(obj, IID_IProvideClassInfo))
    {
        MsgBox IProvideClassInfo interface not supported.
        return
    }

    ; 调用 GetClassInfo 来获取到 ITypeInfo 接口的指针.
    DllCall(vtable(pci, 3), "ptr", pci, "ptr*", ti)

    ; 调用 GetDocumentation 来获取对象的完整类型名称.
    DllCall(vtable(ti, 12), "ptr", ti, "int", -1, "ptr*", pname, "ptr", 0, "ptr", 0, "ptr", 0)

    ; 转换 BSTR 指针为可用的字符串.
    name := StrGet(pname, "UTF-16")

    ; 通过 pname 释放 BSTR 引用.
    DllCall("OleAut32\SysFreeString", "ptr", pname)

    ; 释放原始接口指针.
    ObjRelease(ti)
    ObjRelease(pci)

    ; 显示类型名称!
    MsgBox % "Class name: " name

    vtable(ptr, n) {
        ; NumGet(ptr+0) 返回对象的虚函数表
        ; (简称为 vtable) 的地址. 表达式的其余部分从
        ; vtable 获取第 n 个函数的地址.
        return NumGet(NumGet(ptr+0), n*A_PtrSize)
    }

自动化现有的 Internet Explorer 窗口.

    sURL := "https://www.autohotkey.com/boards/"
    if WebBrowser := GetWebBrowser()
       WebBrowser.Navigate(sURL)
    return

    GetWebBrowser()
    {
        ; 获取到顶级 IE 窗口文档对象的原始指针.
        static msg := DllCall("RegisterWindowMessage", "Str", "WM_HTML_GETOBJECT")
        SendMessage msg, 0, 0, Internet Explorer_Server1, ahk_class IEFrame
        if (ErrorLevel = "FAIL")
            return  ; 未找到 IE.
        lResult := ErrorLevel
        DllCall("oleacc\ObjectFromLresult", "Ptr", lResult
            , "Ptr", GUID(IID_IHTMLDocument2,"{332C4425-26CB-11D0-B483-00C04FD90119}")
            , "Ptr", 0, "Ptr*", pdoc)

        ; 查询 WebBrowserApp 服务. 在这种特殊情况中,
        ; SID 和 IID 相同, 但不总是如此.
        static IID_IWebBrowserApp := "{0002DF05-0000-0000-C000-000000000046}"
        static SID_SWebBrowserApp := IID_IWebBrowserApp
        pweb := ComObjQuery(pdoc, SID_SWebBrowserApp, IID_IWebBrowserApp)

        ; 释放文档对象指针.
        ObjRelease(pdoc)

        ; 返回包装过的可用的 WebBrowser 对象:
        static VT_DISPATCH := 9, F_OWNVALUE := 1
        return ComObject(VT_DISPATCH, pweb, F_OWNVALUE)
    }

    GUID(ByRef GUID, sGUID) ; 转换字符串为二进制的 GUID 并返回其地址.
    {
        VarSetCapacity(GUID, 16, 0)
        return DllCall("ole32\CLSIDFromString", "WStr", sGUID, "Ptr", &GUID) >= 0 ? &GUID : ""
    }

dftg