【问题标题】:Why does instantiating COM object in C# throw exception为什么在 C# 中实例化 COM 对象会引发异常
【发布时间】:2020-03-31 19:50:04
【问题描述】:

我正在尝试在我用 C# (.net 4.7.2) 编写的测试程序中实例化一个在用 Borland C++ 编写的 x86 dll 中定义的 COM 对象。 COM dll(服务器)正在工作,我有一个也用 C++ Borland 编写的 Windows 服务,它可以使用它并从类中实例化一个 COM 对象(使用 CoCreateInstance)。该 dll 已注册,并且 InprocServer32 条目具有该 dll 的正确路径。 typelib 中不存在 coclass,只有接口(存在于 typelib 中)。我使用 TlbImp 创建了我在 c# 项目中引用的 dll:s。在项目中,目标平台设置为 x86。我尝试实例化对象的方式是:

var comType = Type.GetTypeFromProgID("ins.MyComType");
object comObj = Activator.CreateInstance(comType);

但是第二行给了我

“抛出异常:mscorlib.dll 中的‘System.IO.FileNotFoundException’” 带有消息'检索组件的 COM 类工厂 CLSID {C4363C5E-3831-46DF-8701-60C8D1B612BA} 失败,因为 以下错误:8007007e 找不到指定的模块。 (来自 HRESULT 的异常:0x8007007E)。”。

如果我尝试以管理员身份运行应用程序并不重要。我对几年前尝试过类似的事情有一个模糊的记忆,当时它确实有效。它可能在 Win 7 机器上(甚至可能是 32 位系统)。我试图在 DependencyWalker 中打开该项目,但我不确定我在看什么。我收到几个错误:

*错误:未找到至少一个必需的隐式或转发依赖项。 *错误:发现具有不同 CPU 类型的模块。 *错误:检测到循环依赖。 *警告:未找到至少一个延迟加载依赖模块。 *警告:由于延迟加载依赖模块中缺少导出功能,至少有一个模块存在未解析的导入。

有没有人知道它可能导致异常的原因是什么?或者如果我能得到一些关于如何深入研究dependencywalker的提示?我得到了一棵巨大的系统装配树,但我看不到任何明显的装配突出,尽管 DW 将它们中的许多称为 64 位。我的猜测是某个地方的一些依赖 dll(s)应该是 x86,但哪个(s)。我应该安装一个类似的 redist 东西才能让它工作吗?

最好的问候

/埃里克

【问题讨论】:

  • 在注册表中搜索C4363C5E-3831-46DF-8701-60C8D1B612BA,这应该会导致您找到问题dll。
  • 您可以轻松编写一个使用 COM 实例化对象的 10 行 C++ 程序。如果对象实现了 IDispatch,那么您应该编写一个 vbscript,使用 32 位版本的 cscript/wscript(在 c:\windows\syswow64 中)实例化对象。我只是想先去掉 .NET 的东西,因为你说它是用母语编写的。然后,使用 procmon 查看正在尝试加载的模块以及失败的原因。 procmon 向您显示程序查找的注册表项,以及它访问的文件以及它尝试加载的模块。
  • @RamblinRose,因为我试图告知我已经有一个用本机 C++ 编写的应用程序,它可以使用 prog id 从 COM 类实例化 COM 对象以获取 clsid,然后是 CoCreateInstance。在该应用程序中,一切正常。不确定您是否指的是其他内容?
  • @Joseph Willcoxson(另请参阅我之前的评论)。对 vbscript 不太了解,但会尝试研究它。因为我有一个可以实例化 COM 类的本机 c++ 应用程序,所以我主要关心的是为什么 .NET 层(可能)会导致问题。 vbscript 与.NET 有什么关系吗?是否可以将其理解为介于本机和 .NET 之间的某个地方?当我的本机应用程序已经正常工作时,是否有任何目的制作 vbscript?也会看看procmon,谢谢!
  • 这是一个简单的文件未找到错误。使用 SysInternals 的进程监视器找出它正在寻找的 DLL。例如,可以是 Borland C++ 运行时库。

标签: c# c++ com windows-10


【解决方案1】:

您应该编写一个包含以下行的简单 VBScript:

set obj = CreateObject("ins.MyComType")
MsgBox TypeName(obj)

将文件命名为 test.vbs

执行命令:

c:\windows\syswow64\wscript.exe test.vbs

使用来自 syswow64 的版本可确保它使用 32 位版本的 wscript.exe,它可以实例化 32 位 COM 对象。 c:\windows\system32 中的版本只能在 DLL 中实例化 64 位进程内 COM 对象...您说您的对象是 32 位 COM DLL 服务器。

如果 vbscript 失败,则可能是对象不兼容自动化 - 实现 IDispatch。否则,您将收到一条错误消息,为什么它会失败。

如果成功,您将知道 C++ 端可能没有任何问题导致问题。您认为是这种情况……但是 Borland C++ 的运行时在哪里?一切都是静态链接的,还是其中一些是动态链接的?如果它是动态链接的,它在路径中的什么位置?可能是您拥有的 C++ 服务在其路径中有该库,因此当它加载您的 COM 对象时,该库是可用的。但是,当您尝试从 .NET 或 VBScript 等第三方加载时,库的路径就会显示出来。谁知道?我只是提出建议。

如果您使用 ProcMon,它可以查看问题所在。它将向您显示正在读取哪些注册表项以及正在尝试加载哪些文件。

【讨论】:

  • 感谢您的回复。使用脚本开始路径并开始研究使用 ProcMon。但是,所有(以任何方式回答/评论过这个问题的大多数人)你关于丢失 dll 的“唠叨”最终让我认为它可能不是一些模糊的 win x86 系统 dll 丢失,我认为这是理所当然的问题开始(我知道,不好......)。那时我想起了我的 COM dll 使用的“帮助”dll。一旦我将其复制到正确的位置,它就开始正常工作。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-09
  • 1970-01-01
  • 1970-01-01
  • 2013-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多