【问题标题】:COM dll unregister issueCOM dll 注销问题
【发布时间】:2014-08-30 08:39:41
【问题描述】:

我有一个包含许多 COM dll 的项目,为了满足要求,我必须取消注册 COM Dll,我通过调用 Regsvr32 -u 选项来完成此操作,并且 dll 已取消注册。

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

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

对于给定的CoClass,如何删除接口信息,BEGIN_COM_MAP 和COM_INTERFACE_ENTRY 有什么作用吗?

【问题讨论】:

  • 查看类型库时,ICommon接口是否在所有使用ICommon的COM组件dll中可见?
  • 您可能在 2+ 类型库上拥有此接口(典型问题),然后取消注册 ANY 会删除接口注册。
  • 如果这是问题所在,快速解决方法可能是使用此界面重新注册任何剩余的库。一个适当的解决方法是消除类型库上的重复。
  • 谢谢 Roman...如果可行的话我会的

标签: c++ windows com atl dcom


【解决方案1】:

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

这样会破坏任何使用其他实现该接口的 COM 服务器的客户端程序,它们不能再编组该接口,并且它们将在运行时因 E_NOINTERFACE 而死。本身就是一个令人困惑的错误代码,您会假设接口以某种方式消失了,但它实际上抱怨 COM 对象没有实现 IMarshal。 COM 在注册表中找不到键时的最后喘息。

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

对于这种损失没有真正的防御措施,您必须实施一个精心设计的引用计数方案,记录有多少 COM 服务器依赖于代理,并且只删除密钥(以及 DLL,如果它是自定义代理)当它倒计时到零时。这已经完成,但是只需要一个不支持该方案的安装程序,或者像您一样从命令行执行不明智的 Regsvr32.exe /u,就可以使其失败。

【讨论】:

  • 当然,这一切都是对的,但防御很简单——永远不要在 2+ 类型库上拥有接口。那么就不会出现一个东西消失了,而另一个东西还在使用这个消失的东西的情况。 IDL importlib 是一种相互引用类型库的工具。
  • +1 我几乎要逐字逐句地写下来。出于这个原因,我从不合并多个 PE 之间共享的接口的代理存根信息,选择单独的类型库,如果需要一个独立的编组器(我也尽量避免)。
  • 这正是我看到的错误...感谢您抽出时间回答这个问题
【解决方案2】:

是的,这些元素确实起作用,regsvr32 使用的类型库也是如此。

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

我建议将ICommon 接口隔离到单个类型库(COM 组件)并在需要接口的任何地方导入该类型库,从而确保接口的单一“所有者”。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    相关资源
    最近更新 更多