处理来自 C++ DLL 的用户定义异常 - .NET PInvoke/Marshalling

Posted

技术标签:

【中文标题】处理来自 C++ DLL 的用户定义异常 - .NET PInvoke/Marshalling【英文标题】:Handling user-defined exceptions from C++ DLL - .NET PInvoke/Marshalling 【发布时间】:2011-07-19 19:56:35 【问题描述】:

我正在开发使用 PInvoke 在内部调用 C/C++ DLL 的 WPF 应用程序。在 DLL 的调试模式下,每当发生错误时,函数都会抛出异常,该异常基本上是一个定义的结构,其中包含特定的错误消息和特定于模块的应用程序代码。这与正常的 Win32 错误日志记录不同。现在我的问题是我想捕获 DLL 抛出的异常。

如果在 Marshalled 函数周围使用 try catch,.NET 只会通知我说外部模块中发生了错误。

try

    // Marshalled function called

catch(Exception ex)

    MessageBox.show(ex.Message);

现在我了解 C/C+= DLL 异常不是从 .NET 的 Exception 类派生的类,因此 .NET 将无法正确编组它。我无法将 C++ DLL 更改为托管的或对 dll 代码进行任何源代码更改。

我确实在 MSDN 上看到过类似的帖子,其中包含 VC++.NET 中提供的解决方案,其中 DLL 的每个函数都被创建到一个包装器中,抛出一个从 .NET 类派生的异常。

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/0624f3b3-5244-4cb8-be9c-29d464975d20

但是,这将需要另一个 .net 程序集项目,该项目将围绕 VC++.NET 中的大约 200 个函数和结构创建包装器。目前,所有 DLL 函数都已使用 PInvoke 导入 WPF 应用程序,因此任何现有场景的附加组件都是首选。

【问题讨论】:

使用 pinvoke 是错误的入门方式。您必须创建 C++/CLI 包装器来捕获 C++ 异常。 除了重新重写整个 DLL API 并从零开始之外,现在还有什么可以做的吗?我在 MSDN 论坛上提到的帖子有你的解决方案,但在 VC.NET 中,有没有办法在 C#.NET 中创建这样的包装器? 可能重复:***.com/questions/150544/… @yms:就像我在问题中提到的那样,返回的错误代码不是可以映射的 Win32 标准错误,因此 Win32Exception 不会有帮助。但我确实尝试过,但并没有给我想要的结果。 Hans Passant 通过创建托管 c++ 包装器在 MSDN 论坛上为类似问题提供了解决方案,但是由于限制,目前我没有该选项。 K Singh,我实际上特别在考虑这个答案:***.com/questions/150544/… 【参考方案1】:

如果您想继续使用您在 cmets 中指出的 P/invoke,那么您唯一的选择是在 DLL 边界捕获异常。然后,您可以使用错误代码而不是异常将详细信息传递给托管应用程序。如果你想使用 P/invoke 那么你不能允许异常跨越 DLL 边界。

【讨论】:

以上是关于处理来自 C++ DLL 的用户定义异常 - .NET PInvoke/Marshalling的主要内容,如果未能解决你的问题,请参考以下文章

OLEDB - C++ - ATL 的 OLEDB 提供程序示例使 Excel 崩溃(来自 msado15.dll 的未捕获异常)

如何处理 C++ 加载的 C# DLL 中的异常

来自 JNI_CreateJavaVM (jvm.dll) 的异常 0xC0000005

无法加载 DLL“ParkCOM.dll”: 找不到指定的模块。 (异常来自 HRESULT:0x8007007E) 终结者

来自未处理异常的 C++ 堆栈跟踪?

C++:XY.exe 中 0x0b9ec715 (XX.dll) 处的未处理异常:0xC0000005:访问冲突读取位置 0x00000004