簡體   English   中英

從C ++中的接口名稱獲取IID? (VS 2010自動化)

[英]Get IID from interface name in C++? (VS 2010 automation)

在給定COM接口名稱為字符串的情況下,如何獲取相應的IID,以便可以調用QueryInterface()?

例如:

// Attempt to cast IDispatch referenced by pDisp to an ICommandBarButton

char *interface_name = "ICommandBarButton";
IID iid;

<<< code to get the iid for interface_name goes here >>>
hr = pDisp->QueryInterface(iid, &interface);

當然,這假設接口名稱在系統范圍內是唯一的,如果不是,則需要更多上下文。 上下文是我有一個用於自動化VS 2010的腳本引擎,並且需要根據從腳本作為字符串讀取的接口名稱在類型之間進行轉換。 我已經有一個IDispatch *可以投射對象。

編輯:

Alf用戶評論說,我不需要這樣做,很高興不這樣做。 使用ITypeLib,我確定我的IDispatch(由CommandBarControls.Add(msoButton)創建)是CommandBarControl。 我需要一個用於CommandBarButton的IDispatch,以便可以訪問按鈕特有的屬性,例如Style屬性-CommandBarControl IDispatch無法識別該屬性。 我的IDispatch AFAIK支持的接口是:

Interface:CommandBarControl  GUID:43FD5911-7BAC-4BDC-AB6C-2DE65B5C0233
  Interface:IDispatch  GUID:00020400-0000-0000-C000-000000000046
    Interface:IUnknown  GUID:00000000-0000-0000-C000-000000000046

生成如下圖所示。 CommandBarButton未在此處列出,因此希望有人向我展示如何僅使用IDispatch的運行時機制執行此轉換。

實驗代碼:

void
GetTypeInfo(ITypeInfo *pTypeInfo, int indent, char *&p)
{
    BSTR        olename;
    TYPEATTR    *typeattr;
    HRESULT     hr;

    hr = pTypeInfo->GetDocumentation(MEMBERID_NIL, &olename, NULL, NULL, NULL);
    if (hr == S_OK)
    {
        for (int i = 0; i < indent; i++)
            *p++ = ' ';
        p += sprintf(p, "Interface:");
        int len = SysStringLen(olename);
        for (int i = 0; i < len; i++)
            *p++ = (char)olename[i];
        *p++ = ' ';
        SysFreeString(olename);
    }

    hr = pTypeInfo->GetTypeAttr(&typeattr);
    if (hr == S_OK)
    {
        p += sprintf(p, " GUID:");
        for (int i = 0; i < 4; i++)
            p += sprintf(p, "%02X", ((unsigned char*)&typeattr->guid.Data1)[3-i]);
        *p++ = '-';
        for (int i = 0; i < 2; i++)
            p += sprintf(p, "%02X", ((unsigned char*)&typeattr->guid.Data2)[1-i]);
        *p++ = '-';
        for (int i = 0; i < 2; i++)
            p += sprintf(p, "%02X", ((unsigned char*)&typeattr->guid.Data3)[1-i]);
        *p++ = '-';
        for (int i = 0; i < 2; i++)
            p += sprintf(p, "%02X", typeattr->guid.Data4[i]);
        *p++ = '-';
        for (int i = 2; i < 8; i++)
            p += sprintf(p, "%02X", typeattr->guid.Data4[i]);
        *p++ = '\n';
        for (int i = 0; i < typeattr->cImplTypes; i++)
        {
            HREFTYPE reftype;
            ITypeInfo   *pTypeInfo2;
            hr = pTypeInfo->GetRefTypeOfImplType(i, &reftype);
            if (hr == S_OK)
            {
                hr = pTypeInfo->GetRefTypeInfo(reftype, &pTypeInfo2);
                if (hr == S_OK)
                {
                    GetTypeInfo(pTypeInfo2, indent + 2, p);
                    pTypeInfo2->Release();
                }
            }
        }
        pTypeInfo->ReleaseTypeAttr(typeattr);
    }
}


void
GetDispatchInfo(IDispatch *pDisp)
{
    char        buffer[16384];
    char        *p = buffer;
    UINT        ticount;
    HRESULT     hr;

    hr = pDisp->GetTypeInfoCount(&ticount);
    if (hr == S_OK)
    {
        for (UINT ti = 0; ti < ticount; ti++)
        {
            ITypeInfo *pTypeInfo;
            hr = pDisp->GetTypeInfo(ti, 0, &pTypeInfo);
            if (hr == S_OK)
            {
                GetTypeInfo(pTypeInfo, 0, p);
                pTypeInfo->Release();
            }
        }
    }
    *p = 0;
    OutputDebugString(buffer);
}

好的,根據以上評論,我認為原始問題(將接口名稱全局轉換為GUID)是不可能的。

換句話說,Visual Basic解釋器提供了如下命令:

control = commandBar.Controls.Add(MsoControlType.msoControlButton)
button = DirectCast(control, CommandBarButton)

除了在某些系統范圍的表中查找字符串“ CommandBarButton”以外,它還依賴於其他內容。 而且這似乎是在IDispatch及其關聯的類型庫的運行時機制內部的某個地方。 大概有一種方法可以使用某些類型庫voodoo復制VB在這里所做的事情。 但這不是原來的問題。

編輯:

我找到了解決問題的方法,並在相關問題上發布了答案:

IDispatch為CommandBarButton.Style返回DISP_E_UNKNOWNNAME

簡而言之,查詢IDispatch的IUnknown,然后再次查詢IUnknown的IDispatch,返回另一個IDispatch,該IDispatch似乎適用於派生最多的類(在這種情況下為CommandBarButton)。 不需要類型庫伏都教。 希望這對某人有幫助。

如果該接口已注冊(通常用於編組),則您可能會在注冊表中HKCR \\ Interface下找到它。 不幸的是,那里的接口是由IID注冊的,因此,如果您想從名稱中查找IID,則必須進行線性搜索。

即使那樣,也不能保證它能正常工作(接口注冊不是強制性的,我什至不確定在注冊接口名稱時接口名稱是正確的)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM