我的问题类似于获取DLL文件的CLSID?, 我认为.
我有一个带有一些DLL的目录,每个DLL实现一个或多个COM接口.我想得到:
1)每个接口名称2)实现接口的类的CLSID
对于每个DLL.重要的是一切都可以以编程方式完成(所以我不能使用某种COM浏览器并手动查找该信息).
稍后我将查找给定接口名称的CLSID并使用IDispatch调用一些方法.
一种替代方案似乎是扫描注册表,试图匹配类型,接口和类GUID以及.dll文件名.但这似乎很慢而且不健全.
有人有这个问题的明确解决方案吗?
编辑:
根据Ben Voigt的回应,我提供了以下符合我需求的代码:
ITypeLib *typelib;
ITypeInfo *typeinfo;
LoadTypeLibEx(_T("c:\\mydir\\mycom1"), REGKIND_NONE, &typelib);
for (UINT i = 0;i < typelib->GetTypeInfoCount();++i) {
TYPEKIND typekind;
typelib->GetTypeInfoType(i, &typekind);
if (typekind == TKIND_COCLASS) {
// class!
CComBSTR className;
TYPEATTR *typeattr;
typelib->GetTypeInfo(i, &typeinfo);
typeinfo->GetDocumentation(MEMBERID_NIL, &className, NULL, NULL, NULL);
typeinfo->GetTypeAttr(&typeattr);
GUID classGUID = typeattr->guid;
for (UINT j = 0;j < typeattr->cImplTypes;++j) {
// interface!
CComBSTR interfaceName;
HREFTYPE hreftype;
ITypeInfo *classtypeinfo;
typeinfo->GetRefTypeOfImplType(j, &hreftype);
typeinfo->GetRefTypeInfo(hreftype, &classtypeinfo);
classtypeinfo->GetDocumentation(MEMBERID_NIL, &interfaceName, NULL, NULL, NULL);
// associate interfaceName with classGUID here
}
}
}
Run Code Online (Sandbox Code Playgroud)
你不能从COM DLL中获得它,但你可以从类型库中获取它.我很确定MIDL编译器有一个转换来反编译一个类型库,但解析IDL并不像使用TypeLib API那么容易.
更复杂的是,类型库经常作为资源存储在DLL中.因此,您将提取资源,并使用TypeLib API打开它.
从LoadTypeLibEx
哪个开始将返回一个ITypeLib*
接口指针(你知道你需要COM才能获得有关COM库的信息,对吧?).这实际上将为您执行资源提取步骤.
然后,打电话ITypeLib::GetTypeInfoCount
找出有多少种类型.调用ITypeLib::GetTypeInfoType
为每一个找到的接口和组件类.并呼吁ITypeLib::GetTypeInfo
之后ITypeInfo::GetDocumentation
得到的名称.
到目前为止看起来你已经完成了这一切.接下来,您需要使用类型的GUID ITypeInfo::GetTypeAttr
(不是ITypeLib::GetLibAttr
).这会给你一个TYPEATTR
结构,它有一个guid
字段.
从相同的TYPEATTR
结构,你将需要该cImplTypes
领域.与它一起ITypeInfo::GetRefTypeOfImplType
将允许您将每个coclass与它实现的接口相匹配.
请注意,接口和实现coclass之间不能保证1:1的关系.并且界面可以与coclass位于不同的库中.
Ben Voigt的答案很少警告:并非每个COM DLL都有一个类型库。在您看来,确实如此;但这不是必需的。唯一坚如磐石的要求是DLL导出函数DllGetClassObject(),在其中传递CLSID并返回对象工厂。
您可以加载该库并为系统上每个已注册的CLSID调用DllGetClassObject(扫描HKCR \ CLSID下的注册表以获取这些列表)。那些返回有效对象的对象是DLL支持的对象。现在,从理论上讲,甚至不需要注册DLL支持的CLSID。我可以设想一个DLL,该DLL实现只有目标客户端知道的私有对象类,而其他人则不应该知道。但这是一个非常非常奇特的场景。一方面,通过CLSID查找DLL路径的常规COM机制将因此而中断。客户端必须直接加载DLL。
您还可以在注册表中扫描CLSID,其中所考虑的DLL已注册为InprocServer32;同样,这将在私人课程的情况下中断。您可以在regedit
中搜索注册表,搜索数据。此外,您还必须处理文件名大小写问题,短名称与长名称,硬链接,环境变量替换等。所以我不推荐它。
编辑:只是想到了另一种方式。下载Regmon,运行它,然后在DLL上调用regsvr32。然后观察触摸了哪些CLSID。
归档时间: |
|
查看次数: |
8196 次 |
最近记录: |