8

通过 OLE/COM 对象查看器查看由 CCW 创建的生成的 TLB 文件显示 IID 保持不变,除非我更改接口的设计(这是正确的行为),我担心的是,如果我在另一台机器上编译相同的代码尽管接口没有改变并因此破坏现有的 COM 客户端,但仍将生成完全不同的 IID。

  1. COM 可调用包装器如何生成 COM 接口 ID?
  2. CCW如何知道接口是否发生了变化,是否需要生成新的IID?
  3. 只生成我自己的并在源文件中声明会更安全吗?
4

1 回答 1

5

类型的 guid 并不特定于 COM 互操作,所有 .NET 类型都有一个 guid。您可以从 Type.GUID 属性中获取它。生成它的 CLR 中的代码可从 SSCLI20 发行版中获得。您可以通过查看 clr/scr/vm/methodtable.cpp, MethodTable::GetGuid() 方法中的代码来查看算法。

总结算法:

  • 如果该类型具有 [Guid] 属性,则返回该属性
  • 如果类型是接口类型,则生成接口类型定义的字符串化版本。这是由 interoputil.cpp 中的 GetStringizedItfDef() 完成的。它以完全限定的类型名称开头,并附加每个成员定义的字符串版本。
  • 对于所有其他类型,生成该类的字符串化版本。它以完全限定的类型名称开头,附加类名称并附加完全限定的程序集名称。
  • 然后通过辅助函数 CorGuidFromNameW() 将生成的字符串散列到 Guid 中。

这些信息足以回答您的问题:

COM 可调用包装器如何生成 COM 接口 ID?

它使用上述算法生成的 Type.GUID。算法中的任何元素都不是特定于执行它的机器,因此您不必担心在不同的构建机器上获得不同的 IID 和 CLSID。

CCW如何知道接口是否发生了变化,是否需要生成新的IID?

它没有。它完全依赖于为不同接口定义生成不同 GUID 的算法。

只生成我自己的并在源文件中声明会更安全吗?

并不真地。该算法没有记录在案的故障模式。使用您自己的 [Guid] 属性会显着增加您在必要时忘记更改它的几率。这是一个经常使用的快捷方式,也是 DLL Hell 的主要来源。讨厌的那种,使客户端崩溃几乎不可能诊断出硬件异常的那种。与仍然很难但并非不可能的 E_NOINTERFACE 不同。依靠自动生成的 Guid,我只能想到两个缺点:当您忘记在重建程序集之前取消注册程序集时,它往往会在您的开发机器上造成注册表污染。当您对 COM 错误进行故障排除时,它会减慢您的速度,因为您并不容易了解 guid。诚然,注册表污染对我来说已经足够了。

于 2011-07-03T18:31:48.267 回答