I've been writing a lot of code recently that involves interop with the Win32 API and have been starting to wonder what's the best way to deal with native (unmanaged) errors that are caused by calls to Windows API functions.
Currently, the calls to native functions look something like this:
// NativeFunction returns true when successful and false when an error
// occurred. When an error occurs, the MSDN docs usually tell you that the
// error code can be discovered by calling GetLastError (as long as the
// SetLastError flag has been set in the DllImport attribute).
// Marshal.GetLastWin32Error is the equivalent managed function, it seems.
if (!WinApi.NativeFunction(param1, param2, param3))
throw new Win32Exception();
The line that raises the exception can be equivalently rewritten as such I believe:
throw new Win32Exception(Marshal.GetLastWin32Error());
Now, this is all well in that it throws an exception appropriately containing the Win32 error code that was set as well as a (generally) human-readable description of the error as the Message
property of the Exception
object. However, I have been thinking that it would be advisable to modify/wrap at least some, if not all, of these exceptions so that they give a slightly more context-oriented error message, i.e. one more meaningful in whatever situation the native code is being used. I have considered several alternatives for this:
- Specifying a custom error message in the constructor for
Win32Exception
.
throw new Win32Exception(Marshal.GetLastWin32Error(), "My custom error message.");
- Wrapping the
Win32Exception
in another Exception object so that both the original error code and message are retained (theWin32Exception
is now theInnerException
of the parent exception).
throw new Exception("My custom error message.",
Win32Exception(Marshal.GetLastWin32Error()));
The same as 2, except using another
Win32Exception
as the wrapper exception.The same as 2, except using a custom class derived from
Exception
as the wrapper exception.The same as 2, except using a BCL (Base Class Library) exception as the parent when appropiate. Not sure whether it's even appropiate to set the
InnerException
to theWin32Exception
in this case (perhaps for a low-level wrapper but not a higher-level/abstracted interface that doesn't make it obvious that Win32 interop is happening behind the scenes?)
Essentially what I want to know is: what is the recommended practice on dealing with Win32 errors in .NET? I see it done in open-source code in all sorts of different ways, but I was curious whether there were any design guidelines. If not, I'd be interested in your personal preferences here. (Perhaps you even use none of the above methods?)