Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catch unmanaged dll exception in .NET

I'm using an unmanaged DLL with a function that throws std::exception.

I'm using a .NET DLL wrapper so it can be distributed to use in .NET programs.

I would like to be able catch the message from the native exception but all I'm getting is System.Runtime.InteropServices.SEHException("External component has thrown an exception.")

Is there any way to propagate the exception details? Maybe I should export a custom exception from the native DLL? How would I do this?

Thanks

native DLL:

__declspec(dllexport) void __stdcall W32DLLFunc(int param) {
  if (param < 0) {
    throw new exception("Error: param must be > 0");
  }
  ...
}

.net DLL:

[DllImport("nw32.dll", CharSet = CharSet::Auto)]
static void W32DLLFunc(int param);

vb.net program:

Try
  W32DLLFunc(-1)
Catch ex As Exception
  MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
like image 885
Miquel Avatar asked Dec 16 '13 12:12

Miquel


1 Answers

Native C++ exceptions are native C++ exceptions. They don't work with things that aren't C++. They even don't work between different versions of C++.

Native C++ exceptions are not good for interoperability.

The standard mechanism for returning error information from DLLs is to return a value to indicate success or failure and to use SetLastError and GetLastError to communicate an error code if the function failed.

If you want a standard mechanism to return more information than an error code you need to look at COM, which has IErrorInfo.

But it would be simpler just to define some error codes.

If possible, I would alter the original DLL so that it doesn't leak exceptions at all. If this is impossible because existing C++ clients depends on the current design then I would add a parallel API: a new version of each exported function that calls the original, catches exceptions and returns error codes. This is all boilerplate that can be hidden in macros. If you can't touch the DLL I would add a native wrapper to translate the exceptions.

Update

As suggested by IInspectable, another option is to create a mixed-mode assembly.

Add a .Net class to your existing C++ library. This should provide a wrapper for each API function that calls the original API, catches any exception, copies the details into a .Net exception and throws the .Net exception.

By keeping all the native exception handling within the DLL this avoids the problems with C++ exceptions crossing DLL boundaries. The wrapped exceptions can be consumed in any .Net language without the need to create declarations for the exported functions. The only disadvantage is that you need an additional API for interoperability with other native code.

like image 124
arx Avatar answered Oct 15 '22 04:10

arx