Angel Hernández

Extending the Exception class, getting Win32 error messages plus extension methods

Structured Exception Handling (SEH), it’s one of the top used features by developers, it’s not required any more to be dealing with On Error labels or any other less elegant mechanism to handle error conditions, however .NET Framework is an existing layer between our application and the operating system, even when the Exception class describes an error condition it doesn’t provide the error code and message associated to the operating system, that’s why it’s frustrating sometimes to interpret some “less-descriptive” exceptions and hence recovering any Windows error information can be of great help. Throughout the years Windows API has evolved and grown in size and error messages as well, many of these messages can be found in the SDK and WDK, so I had this idea about extending the Exception class by implementing an extension method. Extension methods enable us to “add” methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. They are a special kind of static method, but they are called as if they were instance methods on the extended type. The most common extension methods are  the LINQ standard query operators that add query functionality to the existing IEnumerable and IEnumerable<T>. 

To retrieve the description for a given error code we use the FormatMessage function, as it’s shown below 

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true,
           CallingConvention = CallingConvention.Winapi)]
public static extern int FormatMessage(int dwFlags, int lpSource, int dwMessageId,
                     int dwLanguageId, out StringBuilder lpBuffer,
                       int nSize, IntPtr va_list);

The extension method used is the following

    public static class ExceptionExtension {
    /// <summary>
    /// Gets the win32 error description.
    /// </summary>
    /// <param name="ex">The ex.</param>
    /// <returns></returns>
    public static Win32Error GetWin32ErrorDescription(this Exception ex) {
        Win32Error retval = Win32Error.Empty;
        StringBuilder pMsgBuf = new StringBuilder();
 
        int lastError = FormatErrorHelper.GetLastError();
 
        FormatErrorHelper.FormatMessage(
               FormatErrorHelper.FORMAT_MESSAGE_ALLOCATE_BUFFER |
               FormatErrorHelper.FORMAT_MESSAGE_FROM_SYSTEM,
               FormatErrorHelper.NULL,   lastError, 
               FormatErrorHelper.MakeLangID(FormatErrorHelper.LANG_NEUTRAL,
               FormatErrorHelper.SUBLANG_DEFAULT), out pMsgBuf, 0, IntPtr.Zero);
 
         retval.ErrorCode = lastError;
         retval.Description = pMsgBuf != null ? pMsgBuf.ToString() : string.Empty;
 
         return retval;
      }
}

So if we catch any exception, besides obtaining the exception object itself we get the error and message code from the operating system

Win32Error osError = Win32Error.Empty;
 
try {
// Some funky exception here...
} catch(Exception ex) {
  osError = ex.GetWin32ErrorDescription();
  Console.WriteLine(string.Format("Code: {0} - Description: {1}", 
            new object[] {osError.ErrorCode, osError.Description}));  
}

If we implement everything we’ve previously mentioned, see the difference between the exception message and the message provided by the operating system

image_thumb[2]

Hope this helps,

Regards,

Angel

Leave a Comment

(required) 

(required) 

(optional)

(required)