[英]C++ VS2010 using namespace concurrency; No namespace with that name
[英]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.