2014-09-23 89 views
1

給定COM接口的名稱作爲字符串,我如何獲得相應的IID,以便我可以調用QueryInterface()?從C++的接口名稱中獲取IID? (VS 2010自動化)

例如:

// 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 *用於投射物體。

編輯:

用戶阿爾夫評論說,我不應該要做到這一點,我很高興沒有。使用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); 
} 
+0

通常的interface-uuid關聯機制只是編譯時間。腳本支持基於IDispatch和類型庫。您不需要爲此執行QueryInterface(IDispatch本身除外),您可以使用IDispatch的運行時機制。這就是它的目的。爲什麼不使用它。 – 2014-09-23 22:16:31

+0

謝謝Alf,我修改了這個問題。 – Chungzuwalla 2014-09-23 23:00:44

+1

這是不可能的。 COM關心的唯一事情是{guid}。接口的名字是程序員從來沒有正確使用的逃離細節。編程方便,當你必須與另一個程序交互時,它很快就會消失。大家都稱之爲IMyInterface,或者是一些沒有靈感的變化。這是行不通的,接口必須是全局唯一的。 GU在guid中。 – 2014-09-23 23:54:58

回答

2

OK,基於上述意見,我認爲原來的問題(轉換接口名稱爲GUID全球)是不可能的。

換句話說,在Visual Basic解釋器,用命令提出像這樣的:

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

依靠比查找在某些系統範圍的表中的字符串「CommandBarButton的」其他東西。而且這似乎是IDispatch及其關聯類型庫的運行時機制內的某個地方。大概有一種方法來複制VB在這裏做的事情,使用一些類型的庫巫術。但是,這並不是什麼問原來的問題....

編輯:

我找到了一個解決辦法,以我的問題,並張貼在回答對我相關的問題:

IDispatch returns DISP_E_UNKNOWNNAME for CommandBarButton.Style

在簡而言之,查詢IDispatch的IUnknown,然後再次查詢Iisnkatch以查找IDispatch,返回一個不同的IDispatch,它看起來是最派生類(在這種情況下是CommandBarButton)。沒有需要的類型庫伏都教。 希望這可以幫助別人。

+1

道具在找到答案後給出答案。 – Medinoc 2014-12-16 13:42:28

0

如果接口已註冊(通常用於編組),那麼您可以在註冊表中的HKCR \ Interface下找到它。不幸的是,那裏的接口是由IID註冊的,所以如果你想從名字中找到IID,你必須做一個線性搜索。

即使如此,它不能保證工作(接口註冊不是強制性的,我甚至不知道當註冊接口名稱時)。

+1

調試器已經這樣做:) – 2014-10-28 22:54:28