【问题标题】:C++ DLL Throws Exception at RuntimeC++ DLL 在运行时抛出异常
【发布时间】:2010-12-15 17:40:37
【问题描述】:

我的 C# 应用程序在运行时调用 C++ DLL 中的函数并引发异常。生成的错误代码是 262。不幸的是,Microsoft documentation 缺少此代码。

奇怪的是,从 C++ 测试应用程序运行 DLL 时不会引发此异常,该应用程序是与 DLL 相同的 Visual Studio 解决方案的一部分(单独的项目)。 (C# 应用程序在一个完全独立的解决方案中。)通过调用 CoInitializeEx 返回错误代码,这会初始化 COM,并且是我的应用程序用来查询 WMI 的第一步。

似乎唯一相关的另一件事是,当我使用 Dependency Walker 打开 DLL 时,我收到以下错误和警告:

错误:未找到至少一个必需的隐式或转发依赖项。
警告:至少没有找到一个延迟加载依赖模块。
警告:由于延迟加载依赖模块中缺少导出功能,至少有一个模块存在未解析的导入。

我唯一想到的是缺少的“必需的隐式或转发依赖项”具有使CoInitializeEx 工作所需的东西。根据 Dependency Walker 的说法,找不到这些模块:

  • MSVCR90D.DLL
  • IESHIMS.DLL
  • WER.DLL

感谢任何想法或建议。谢谢。

【问题讨论】:

  • 你很幸运。上次我遇到链接器问题(这在 Microsoft 世界中完全是一团糟……)我的代码在没有任何警告的情况下崩溃了,我花了几个小时才找出问题所在。您应该注意将调用 DLL 的程序与 DLL 链接到的同一运行时库链接。

标签: c# c++ exception dll com


【解决方案1】:

您的错误处理不是 kosher,您可能得到的真正错误是 0x80010106,最后一个字是 262。错误代码是 RPC_E_CHANGED_MODE,“设置后无法更改线程模式”。这是 CoInitialize/Ex 在之前被调用时返回的内容,并且您正试图从 STA 更改为 MTA 或其他方式。

这是不可能的,线程的单元状态在第一次调用 CoInitializeEx() 时被锁定。您需要找出第一个呼叫发生的位置。例如,这可以由 CLR 为托管线程完成。线程的单元状态由启动线程的 Main() 方法上的 [STAThread] 或 [MTAThread] 确定。或者您自己创建的托管线程的 Thread.SetApartmentState()。线程池线程始终是 MTA,无法更改。

更改线程的单元状态可能会产生许多副作用。

【讨论】:

  • 汉斯,我想你可能正在做点什么。这个 C# 应用程序中有很多我无法控制的代码。这是一个现场应用程序,我正在更新它以支持一些新硬件。有没有办法确定性地检查是否应该在我的 C++ DLL 中调用 CoInitializeEx?或者有没有办法以编程方式检查线程的公寓状态?谢谢。
  • C++ DLL 调用 CoInitializeEx() 几乎总是错误的。除非它自己创建了线程。
  • 好的,但不幸的是,我不能指望这一点。如果我在有条件地调用 CoInitializeEx 之前评估 CO_E_NOTINITIALIZEDCoGetApartmentType 的返回值会怎样?
  • 许多程序员在遇到问题时会想“我知道,我会使用线程”。现在他有两个问题。
  • @Jim,在您的特定情况下,单独的线程可能是您可以使用的最佳选择。从 DLL 创建线程是一件麻烦事,因为 DLL 不拥有进程的生命周期; EXE 可以。但是...如果您以同步方式运行它(创建线程,初始化,等待线程完成,然后继续),您通常是安全的。您可以缓存线程,因此您不必每次都创建和 CoInitialize() 它,但不要让它在后台工作并返回给您的调用者:再次出现微妙的生命周期问题。
【解决方案2】:

在您的特定情况下,单独的线程可能是您可以使用的最佳选择。

从 DLL 创建线程是一件麻烦事,因为 DLL 不拥有进程的生命周期;所有者是EXE。

但是... 如果您以同步方式运行它(创建线程;初始化;等待线程完成;然后继续),您通常是安全的。您可以缓存线程,因此您不必每次都创建和 CoInitialize() 它,但不要让它在后台工作并返回给您的调用者:再次出现微妙的生命周期问题。

【讨论】:

  • 另外,请查看@Hans 的回复,了解有关问题诊断的重要信息。
【解决方案3】:

我假设您没有安装 Visual Studio 2008 C++,因为您将安装 MSVCR90D.dll 此 dll 是仅调试 dll,这意味着您正在尝试加载已编译为调试 DLL 的 DLL。

至于其他...请参阅此主题:Dependency Walker reports IESHIMS.DLL and WER.DLL missing?

【讨论】:

    【解决方案4】:

    检查您是否已在发布或调试模式下编译所有内容。

    您是否使用任何来自 I.E 的基于 http 的功能?我很好奇你为什么依赖 ieshims.dll。

    【讨论】:

      【解决方案5】:

      错误 WIN32=262 是 HRESULT=-2147024634 (0x80070106)。这是另一回事。 CoInitializeEx 应该只为每个线程调用一次,但如果调用不止一次,则每个CoInitializeEx 都应该有一个CoUninitialize

      【讨论】:

      • 如果你打-1,你应该解释自己。
      猜你喜欢
      • 1970-01-01
      • 2011-07-03
      • 2012-01-28
      • 2011-12-29
      • 1970-01-01
      • 2012-08-21
      • 2015-06-03
      • 2019-08-20
      • 1970-01-01
      相关资源
      最近更新 更多