給定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);
}
通常的interface-uuid關聯機制只是編譯時間。腳本支持基於IDispatch和類型庫。您不需要爲此執行QueryInterface(IDispatch本身除外),您可以使用IDispatch的運行時機制。這就是它的目的。爲什麼不使用它。 – 2014-09-23 22:16:31
謝謝Alf,我修改了這個問題。 – Chungzuwalla 2014-09-23 23:00:44
這是不可能的。 COM關心的唯一事情是{guid}。接口的名字是程序員從來沒有正確使用的逃離細節。編程方便,當你必須與另一個程序交互時,它很快就會消失。大家都稱之爲IMyInterface,或者是一些沒有靈感的變化。這是行不通的,接口必須是全局唯一的。 GU在guid中。 – 2014-09-23 23:54:58