FormatMessage Shortcut for Win32 Error Codes

If you ever need to P/Invoke to an API that returns extended error information via the GetLastError function, then you’ve also probably been through the pain of converting the error code into a usable error message via the FormatMessage API  … not exactly one of the more user-friendly APIs for managed code callers.

Thankfully, there’s a shortcut way to get this message, exposed through the Win32Exception class.  Simply doing this:

string errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;

Will prevent you from needing to call FormatMessage to get an error message for an error code.

Of course you also need to remember to set the SetLastError named parameter on your DllImport attribute to true, and obtain the error code through a call to Marshal.GetLastWin32Error, since P/Invoking to GetLastError directly will generally not work (since the last error may have been set again by another API that the CLR has called).  If you’re using VB.Net, Err.LastDllError is also an acceptable way of accessing the last error code.

Comments (5)

  1. Evgeny M says:

    Something in the area, related to ComExceptions.

    To retrieve hresult from com exception use:

    uint HResult = (uint)Marshal.GetHRForException(ex);

  2. Richard says:

    Actually, you can simplify the call to:

    string errorMessage = new Win32Exception().Message;

    The default constructor for the Win32Excpeption calls Marshall.GetLastWin32Error for you.

  3. Good point Richard — thanks for the tip.


  4. jholder says:

    One good thing I wanted to point out about writing it this way (at least for learning purposes):

    string errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;

    is that it is obvious I can stick an int in there and get out the message:

    int errcode = somefunction();

    string errorMessage = new Win32Exception(errcode).Message;

    Just a quick observation.

  5. Dan Ware says:

    You can also get more info about a COMException as it has an error code;



    Catch ex As COMException

     New ComponentModel.Win32Exception(CType(ex, Runtime.InteropServices.COMException).ErrorCode).Message

    End Try