2

我们有一个 COM 组件项目和一个注册 COM 组件的 Windows 安装项目。我检查了安装项目的先前版本,似乎为 COM 项目中的类生成的 CLSID 总是发生变化,即使有时这些类没有变化。这在某种程度上是我们想要的方式,因为我们希望在同一台机器上保留不同版本的实现。但是,当我手动构建此项目并在同一天多次使用 /regfile 选项运行 regasm.exe 时,生成的 reg 文件中的 CLSID 始终相同。它认为在以前的情况下它们发生了变化,这是因为它们是在不同的日子建造的,但我不确定。那么谁能告诉我这个 CLSID 自动生成的(默认)规则是什么?我认为我们正在使用项目中的默认设置。

我不确定程序集版本是否会影响结果。但是我们将程序集版本号指定为 Major.Minor.*,这意味着第三个数字(内部版本号)是自 1.1.2000 以来的天数,第四个数字(修订号)是自午夜以来的秒数除以 2。在 CLSID 发生变化的情况下,即使类代码不变,主次编号也相同。因此,如果版本号确实影响 CLSID,我可以说它不仅考虑了主要和次要数字。

当然,我们没有为这些类分配静态 GUID,否则它不会在我们的安装项目中改变。

谢谢你的帮助!

4

1 回答 1

2

是的,如果您没有明确使用 [Guid] 属性,CLR 会自动为接口和类生成 guid。它做得很好,它包括程序集和类声明的所有部分,这些部分可能会使您的代码二进制文件与以前的版本不兼容。在 COM 中非常重要,这种不兼容性可能非常难以诊断。

该算法使用完全指定的类型名称以及类型中方法和字段的声明。将它们转换为字符串(“将声明字符串化”)并通过散列将结果字符串转换为 guid。“完全指定的类型名称”是您的克星,其中包括 [AssemblyVersion]。这完全有道理,增加程序集版本是一件大事,它使程序集与使用该程序集的任何代码都不兼容。这样的代码必须重新编译。COM 客户端也不例外。

如前所述,您可以指定自己的 [Guid] 属性以强制 CLSID 为特定值。当您出错并进行重大更改但不重新编译客户端代码时,可能会调用 DLL Hell。失败模式是讨厌的、非常随机的 AccessViolation 异常,或者只是简单地调用了错误的方法。执行此操作时,您应该回退到 ComInterfaceType.IsIDispatch,以便客户端代码被迫使用后期绑定。或者用铁腕控制您的构建和部署过程。

于 2012-08-01T12:08:36.787 回答