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:
Win32Exception
.throw new Win32Exception(Marshal.GetLastWin32Error(), "My custom error message.");
Win32Exception
in another Exception object so that both the original error code and message are retained (the Win32Exception
is now the InnerException
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 the Win32Exception
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?)
This isn't really specific to Win32 exceptions; the question is, when should two different error cases be identified by two different Exception-derived types, and when should they throw the same type with different values stored inside it?
Unfortunately this is impossible to answer without knowing in advance all the situations your code will be called in. :) This is the problem with only being able to filter exceptions by type. Broadly speaking, if you have a strong feeling that it would be useful to treat two error cases differently, throw different types.
Otherwise, it is frequently the case that the string returned by Exception.Message just needs to be logged or displayed to the user.
If there is additional information, wrap the Win32Exception with something more high-level of your own. For example, you're trying to do something to a file, and the user you're running under doesn't have permission to do it. Catch the Win32Exception, wrap it in an exception class of your own, whose message gives the filename and the operation being attempted, followed by the inner exception's message.