解决COM相关错误0x80040154的技巧?

时间:2011-07-15 18:25:31

标签: c# com .net-4.0 interop com-interop

更新了更多调试信息

我正在运行一个我没有源代码的专有软件包,它有一个基于COM的插件接口。我有一个COM可见的.NET程序集,应用程序可以在一台计算机上成功加载,但不能在另一台计算机上加载。

过去两天我一直在这个问题上工作,我觉得我漫无目的地在COM风景中徘徊。在没有加载我的插件的系统上,当我使用regasm /codebase /tlb时,生成并成功注册了tlb。

当我查看可用的唯一日志文件时,它提到它无法创建对象,并返回错误代码0x80040154。

我无法弄清楚为什么无法创建对象,我希望有人可以提出一些调试策略。这是我已经尝试过的,没有成功:

  • 将我的DLL及其依赖项从工作计算机复制到非工作计算机
  • 在非工作计算机上安装VS2010(工作计算机安装了它)
  • 比较我的DLL的Dependency Walker及其在两台计算机上的依赖关系的结果(它们是相同的)
  • 使用了ListDLL。两个系统都加载相同的DLL
  • 运行Process Monitor并在运行regasm /codebase /tlb时对程序集的CLSID进行过滤。除了PID和日期戳之外,两个日志都相同,即使工作系统创建了tlb并且注册成功,并且非工作系统注册了程序集,但没有创建tlb。
  • 运行Process Monitor并在运行应用程序时对程序集的CLSID进行过滤。工作系统在日志中有几个条目,但是非工作系统没有,我相信这是因为没有创建tlb。
  • 在工作系统上查看了OleView,其中列出了使用其下方的类型库的程序集。非工作系统列出了程序集,但没有关联类型库。见下文。

以下是OleView在工作和非工作系统上的程序集条目之间的差异:

  • 工作系统在程序集下有一个条目,我假设它对应于生成和注册的类型库。非工作系统没有。
  • 非工作系统上的
  • _Object在名为InprocServer32[InprocServer32] = (gibberish here)的CLSID下有一个额外的值。
  • 非工作系统上的IConnectionPointContainer具有与上述相同的InprocServer32条目
  • 对于IDispatch,IManagedObject和IProvideClassInfo
  • 也是如此

我会查看注册表,也许我需要删除这些额外的条目并尝试再次运行regasm?

编辑 - 我解决了这个问题。谢谢大家的帮助。事实证明,两个系统上都缺少一个文件,但无论出于何种原因,regasm在一个系统上工作,而不是另一个。我怀疑可能有一个更改,其中依赖项被复制到系统路径中的文件夹!所以我做了一个冰雹玛丽,复制了dll,并且在没有任何消息的情况下执行了regasm。然后应用程序成功加载了插件!

3 个答案:

答案 0 :(得分:4)

我假设生成“未注册类”错误的组件是你的,对吧?换句话说,您是否确定日志中它正在尝试CoCreate您的对象?只是一个健全检查。

您可能想尝试使用Oleview.exe之类的工具直接创建COM对象。自从我使用它已经有一段时间了,但我记得你可以找到你的课程,然后尝试直接实例化。

您还可能需要启动procmon(sysinternals.com)之类的工具,并捕获错误发生时正在读取的注册表项。过滤RegOpenKey操作(操作是RegOpenKey)并查找不成功的结果(结果不是SUCCESS)。这有点单调乏味,但通过比较两台机器之间的reg轨迹,它可能会为您指出答案。

祝你好运!

约翰

答案 1 :(得分:3)

它适用于你的开发机器,而不是目标机器,它们是相同的,可以消除许多可能的故障模式。只剩下一个了:它可以在您的开发机上运行,​​因为您让IDE为您注册程序集。在这种情况下,您使用Regasm.exe错误。您必须将它与/ codebase选项一起使用。忘记/ tlb选项,这是编译器。

使用/ codebase,程序集将在其所在的目录中注册。你会收到来自Regasm的警告,告诉你即将进入DLL地狱。在这种情况下你无能为力,所以忽略那个警告。如果没有/ codebase,你必须使用gacutil.exe将程序集放在GAC中,以便找到程序集。

最终的故障排除策略是使用SysInternals的ProcMon实用程序并查看显示应用程序搜索COM组件的跟踪记录。你会看到它戳了注册信息的HKLM\Software\Classes\CLSID\{guid}密钥。与使用Regedit.exe看到的内容相比。如果您看到Wow6432Node被搜索,那么您在64位操作系统上运行,并且必须使用32位版本的Regasm.exe来注册程序集。

答案 2 :(得分:2)

这两个系统是否有不同的CPU架构?如果是这种情况,可能是您的COM对象显式构建为X86 CPU而不是AnyCPU,在这种情况下,您可能需要将客户端应用程序构建为X86以避免X64系统中的兼容性问题。