如何从ProgID或CLSID获取类型库(而不加载COM对象)?

8

如何在程序中通过ProgID或CLSID获取一个类型库的路径或LIBID,而无需实例化该类型库中包含的COM类?

对于某些COM对象,可以通过注册表路径来实现此目的。

HKEY_CLASSES_ROOT\CLSID\{clsid}\TypeLib

但是有些COM对象没有TypeLib键,例如Word.Application

enter image description here

我如何确定这些COM对象的类型库路径或LIBID,而不实例化COM对象?


有一个很好的微软工具,在处理com/ole对象时非常有帮助,它叫做 oleview。这可以帮助您找到库的路径。 - AquilaRapax
@AquilaRapax:我正在寻找一种以编程方式实现的方法。 - user128300
2个回答

2

类型库可能与给定的 CLSID 相关联,也可能不相关联。如果您在注册表上没有类型库引用,您可以尝试在运行时使用 IDispatch::GetTypeInfo 获取它。

没有类型库(或已注册的类型库)的 COM 类仍然是有效的 COM 类,因此您可能会发现它在没有类型库的情况下运行良好且可用。

你还有一种机会,就是找到托管COM服务器的二进制文件,无论它是 .EXE.DLL 还是 .OCX,并尝试从其资源中加载类型库(通常在标识符为1的位置)。很多情况下,类型库就在那里。


抱歉,在我的问题中我忘了提到,我正在寻找一种在不实例化COM对象的情况下实现这个的方法。尽管如此,还是给你点赞。 - user128300
添加了另一个段落(请参见上文)。 - Roman R.
不幸的是,并非所有的COM对象都将类型库存储为资源(例如Word.Application,它将类型库存储在单独的文件中)。 - user128300
在这种情况下,你能做的事情很少。 - Roman R.

0

正如您在问题中提到的,不是所有的COM对象都在注册表中具有 ID,甚至它们也没有被强制将其TypeLib发送到目标系统,但为了能够公开其对象信息,它们需要一个TypeLib。因此,通常它们的TypeLib信息存储在或中作为资源。您可以使用LoadTypeLib函数从指定模块中提取TypeLib信息作为ITypeLib,然后编写自己的,甚至提取资源,然后将其保存为<.tlb>。


你如何确定 LoadTypeLib 所需的文件路径? - user128300
当然,从注册表中查找,与COM相同,找到实例化您的类所需的模块,因此如果在注册表中有TypeLib,则使用它,否则从InprocHandler32InporcServer32LocalServer32中查找模块,然后在调用LoadTypeLib时使用它。 - BigBoss
你提到的注册表键包含托管COM对象的DLL或EXE的路径;这些注册表键不包含类型库文件(.TLB或.OLB)的路径。 - user128300
当然可以!我在我的回答中告诉你,“它很常见,它们的TypeLib信息存储在EXE或DLL中作为资源”,看一下LoadTypeLib,它可以加载包含类型库和模块的类型库作为资源。 - BigBoss
不幸的是,并非所有的COM对象都将类型库存储为资源(例如Word.Application,它将类型库存储在单独的文件中)。 - user128300
因此,如果对象未分配类型库并且不包含类型库作为资源,则无法动态查找该信息,您应该使用其他类型的库(例如来自发布者的资源)或在运行时使用其类型信息使用 GetTypeInfo。这对您来说不是一个选项。也许你应该祈求奇迹 :) - BigBoss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接