COM dll注销问题

COM dll unregister issue

本文关键字:问题 注销 dll COM      更新时间:2023-10-16

我有一个有许多COM Dll的项目,对于一个要求,我必须取消注册一个COM Dll,我通过调用Regsvr32 -u选项和Dll是未注册的。

这个注销操作似乎删除了一个接口,比如ICommon接口,它使其他COM对象无法使用。

这个ICommon接口是由所有其他COM组件实现的,在未注册的COM Dll的注册表脚本中,我没有看到任何从注册表中删除这个ICommon接口的代码,这是如何被删除的。

如何为给定的CoClass删除接口信息,是否BEGIN_COM_MAP和COM_INTERFACE_ENTRY发挥任何作用?

COM充斥着DLL Hell问题。这里的失败模式是卸载服务器也会从HKLMSoftwareClassesInterface中删除密钥。它告诉COM应该使用哪个代理/存根实现来跨单元边界封送接口。接口的ProxyStubClsId32键标识代理。

所以这会破坏任何使用其他COM服务器实现接口的客户端程序,它们不能再封送接口,并且它们将在运行时死于E_NOINTERFACE。它本身就是一个令人困惑的错误代码,你会认为接口不知怎么消失了,但它实际上是在抱怨COM对象没有实现immarshal。COM在注册表中找不到键时的最后喘息。

这通常不是很难修复,你只需要重新注册失败的COM服务器,它会把密钥放回去。

没有真正的防御这种损失,你必须实现一个详细的引用计数方案,记录有多少COM服务器依赖于代理,只有当它计数到零时才删除键(和DLL,如果它是一个自定义代理)。这已经完成了,但是只需要一个不购买方案的单个安装程序,或者像您一样从命令行执行不明智的Regsvr32.exe/u,就可以使其失败。

是的,这些元素确实发挥了作用,regsvr32使用的typelib也是如此。

如果ICommon接口是可见的,通过查看COM组件的typelib可以看到,该类型被视为由组件"拥有",并且regsvr32进程将该组件添加为该接口的位置。在移除时,情况正好相反。因此,虽然仍然使用ICommon接口,但由于被视为接口的"所有者"的组件被删除,接口的注册也被删除。新的"所有者"不会自动安装(或注册),这必须通过再次注册合适的组件来完成。

我建议将ICommon接口隔离为单个typelib (COM组件),并在需要接口的任何地方导入该typelib,从而确保接口的单个"所有者"。

注意:基于一些继承代码的经验(有这个问题)我不得不修复,导入或试图重新声明系统接口(例如ISerializable等)时要非常小心,因为regsvr32也可以从注册表中删除这些;造成了世界的痛苦。在这种情况下,卸载几乎破坏了整个系统。