.NET COM Callable Wrapper如何生成IIDs?

8
通过OLE/COM对象查看器查看CCW生成的TLB文件,可以发现除非我更改了接口的设计(这是正确的行为),否则IID保持不变。但我的担心是,如果我在另一台机器上编译相同的代码,则会生成完全不同的IID,尽管接口没有改变,从而破坏现有的COM客户端。
以下是需要回答的问题:
1. COM Callable Wrapper如何生成COM接口ID? 2. CCW如何知道接口是否已更改并需要生成新的IID? 3. 是否更安全地自己生成IID并在源文件中声明?
1个回答

5
一个类型的GUID并不仅仅是COM互操作所特有的,所有.NET类型都有一个GUID。您可以从Type.GUID属性中获取它。生成它的CLR代码可以在SSCLI20分发版中找到。您可以通过查看clr/scr/vm/methodtable.cpp文件中MethodTable::GetGuid()方法中的代码来了解算法。
算法总结如下:
- 如果该类型具有[Guid]属性,则返回该属性; - 如果该类型是接口类型,则生成接口类型定义的字符串化版本。这是在interoputil.cpp文件中GetStringizedItfDef()函数完成的。它从完全限定的类型名称开始,并附加每个成员定义的字符串版本; - 对于所有其他类型,生成类的字符串化版本。它从完全限定的类型名称开始,附加类名,然后附加完全限定的程序集名称; - 然后将结果字符串哈希为GUID,使用辅助函数CorGuidFromNameW()。
这足以回答您的问题:
“COM Callable Wrapper如何生成COM接口ID?”
它使用上述算法生成的Type.GUID。算法中的所有元素都不特定于执行它的机器,因此您不必担心在不同的构建机器上获得不同的IID和CLSID。
“CCW如何知道接口是否已更改并需要生成新的IID?”
它不知道。它完全依赖于算法为不同的接口定义生成不同的GUID。
“只生成我的GUID并在源文件中声明是否更安全?”
不是真的。对于此算法,没有记录的故障模式。使用自己的[Guid]属性显着增加了忘记在必要时更改它的可能性。这是经常采用的快捷方式,也是DLL Hell的主要来源。恶意的那种,会导致客户端崩溃,并且几乎不可能诊断硬件异常。与仍然困难但不是不可能的E_NOINTERFACE相反。我只能想到两个依靠自动生成的GUID的缺点:当您重建它们之前忘记取消注册程序集时,它往往会在开发机器上造成注册表污染。当您正在解决COM错误时,它会使您的速度变慢,因为您不知道GUID。可以承认,注册表污染足以让我放弃这种方法。

使用自己的[Guid]属性会显著增加忘记在必须更改时更改它的可能性。为什么我必须更改生成的GUID? - Konrad
如果我使用自动生成的GUID,它会如何污染注册表?难道它不应该只是在同一位置覆盖注册表吗? - Konrad
还有一个选项“注册COM互操作”,据说可以为我完成所有的“注销”操作,以防止污染。 - Konrad

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