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

发布于 2024-11-24 08:48:28 字数 1435 浏览 3 评论 0原文

更新了更多调试信息

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

这两天我一直在研究这个问题,我感觉我在 COM 领域漫无目的地徘徊。在未加载我的插件的系统上,当我使用 regasm /codebase /tlb 时,tlb 已生成并注册成功。

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

我不明白为什么无法创建该对象,希望有人可以建议一些调试策略。这是我已经尝试过的方法,但没有成功:

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

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

  • 工作系统在程序集下有一个条目,我认为该条目对应于生成和注册的类型库。非工作系统则不然。
  • 非工作系统上的_Object 在 CLSID 下有一个名为 InprocServer32[InprocServer32] =(此处为乱码)的额外值
  • 非工作系统上的 IConnectionPointContainer 具有与上面相同的 InprocServer32 条目,
  • 对于 IDispatch、IManagedObject 和 IProvideClassInfo 也相同

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

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

Updated with more debugging info

I'm running a proprietary software package that I don't have source for, and it has a plugin interface that is COM-based. I have a .NET assembly that is COM-visible that the application successfully loads on one computer, but not on another.

I've been working for the past two days on this problem, and I feel like I am aimlessly wandering the COM landscape. On the system that doesn't load my plugin, when I use regasm /codebase /tlb, the tlb is generated and registered successfully.

When I look at the only log file available to me, it mentions that it can't create the object, and returns the error code 0x80040154.

I can't figure out why the object can't be created, and am hoping that someone can suggest some debugging strategies. Here is what I have already tried, without success:

  • copy my DLL and its dependencies from the working computer to the non-working computer
  • installing VS2010 on the non-working computer (the working computer had it installed)
  • comparing the results of Dependency Walker for my DLL and its dependencies on both computers (they were identical)
  • used ListDLLs. Both systems load the same DLLs
  • ran Process Monitor and filtered on the CLSID for the assembly while running regasm /codebase /tlb. Both logs were identical except for the PIDs and datestamps, even though the working system create the tlb and registered successfully, and the non-working system registered the assembly, but didn't create the tlb.
  • ran Process Monitor and filtered on the CLSID for the assembly while running the application. The working system had several entries in the log, but the non-working system had none, which I believe is expected since the tlb didn't get created.
  • looked at OleView on working system, which had the assembly listed with the typelibrary beneath it. The non-working system had the assembly listed, but did not have an associate type library. See below.

Here are the the differences between the assembly's entry in OleView on the working and non-working systems:

  • Working system has an entry under the assembly that I assume corresponds to the typelibrary that was generated and registered. Non-working system does not.
  • _Object on non-working system has an extra value under CLSID called InprocServer32[InprocServer32] = (gibberish here).
  • IConnectionPointContainer on non-working system has the same InprocServer32 entry as above
  • same for IDispatch, IManagedObject, and IProvideClassInfo

I'll look through the registry, and perhaps I need to remove those extra entries and try to run regasm again?

EDIT -- I solved the problem. Thanks everyone for your help. It turns out that a file was missing on both systems, but for whatever reason, regasm worked on one, and not the other. I'm suspicious that there may have been a change where a dependency was copied to a folder that was in the system path! So I did a hail mary, copied over the dll, and regasm executed without any messages. And then the application loaded the plugin successfully!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风尘浪孓 2024-12-01 08:48:28

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

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

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

祝你好运!

约翰

I'm assuming that the component generating the "class not registered" error is yours, right? In other words, are you sure from the log that it's trying to CoCreate your object? Just a sanity check.

You might want to try directly creating your COM object using a tool like Oleview.exe. It's been a while since I've used it but I remember that you can find your class, then try to instantiate it directly.

You also might want to fire up a tool like procmon (sysinternals.com) and capture what registry entries are being read at the time that the error occurs. Filter on RegOpenKey operations (Operation is RegOpenKey) and look for unsuccessful results (Result is not SUCCESS). It's a bit tedious but by comparing the reg traces between the 2 machines it might point you to the answer.

Good luck!

John

决绝 2024-12-01 08:48:28

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

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

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

That it works on your dev machine and not the target machine and that they are identical eliminates many possible failure modes. There's only one left: it works on your dev machine because you let the IDE register the assembly for you. In which case you use Regasm.exe incorrectly. You must use it with the /codebase option. Forget about the /tlb option, that's for compilers.

With /codebase, the assembly gets registered in the directory it is located. You'll get a warning from Regasm, telling you that you are about to enter DLL Hell. Nothing you can do about that in this case so ignore that warning. Without /codebase you must put the assembly in the GAC with gacutil.exe so the assembly can be found.

The ultimate troubleshooting strategy is to use SysInternals' ProcMon utility and look at the trace records that show the app searching for the COM component. You'll see it poking the HKLM\Software\Classes\CLSID\{guid} key for the registration info. Compare with what you see using Regedit.exe. If you see Wow6432Node getting searched then you're running on a 64-bit operating system and have to use the 32-bit version of Regasm.exe to register the assembly.

提赋 2024-12-01 08:48:28

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

Do the two systems have different CPU architectures? If this is the case, it is possible that your COM object was built as X86 CPU explicitly instead of AnyCPU, in that case, you may need to build your client application as X86 as well to avoid compatibility issues in X64 systems.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文