you will need the following signature of dllimports
[DllImport("kernel32.dll")] static extern uint FormatMessage(uint dwFlags, IntPtr lpSource, uint dwMessageId, uint dwLanguageId, [Out] StringBuilder lpBuffer, uint nSize, IntPtr Arguments); // the version, the sample is built upon: [DllImport("Kernel32.dll", SetLastError=true)] static extern uint FormatMessage( uint dwFlags, IntPtr lpSource, uint dwMessageId, uint dwLanguageId, ref IntPtr lpBuffer, uint nSize, IntPtr pArguments); // the parameters can also be passed as a string array: [DllImport("Kernel32.dll", SetLastError=true)] static extern uint FormatMessage( uint dwFlags, IntPtr lpSource, uint dwMessageId, uint dwLanguageId, ref IntPtr lpBuffer, uint nSize, string[] Arguments); // see the sample code [DllImport("kernel32.dll", SetLastError = true)] static extern uint FormatMessage(uint dwFlags, IntPtr lpSource, uint dwMessageId, uint dwLanguageId, [Out] StringBuilder lpBuffer, uint nSize, string[] Arguments);we will also need to use the following constants definition, which is copied from the header files.
// from header files const uint FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100; const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200; const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; const uint FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000; const uint FORMAT_MESSAGE_FROM_HMODULE = 0x00000800; const uint FORMAT_MESSAGE_FROM_STRING = 0x00000400;And I have provided two method that I believe shall be commonly used.
static string FormatNativeMessage(string formatExpression, string[] formatArgs); static string FormatLastWin32Message(uint error);here is the code .
class Program { // check out the quick acess to pinovke [DllImport("kernel32.dll", SetLastError = true)] static extern uint FormatMessage(uint dwFlags, IntPtr lpSource, uint dwMessageId, uint dwLanguageId, ref IntPtr lpBuffer, uint nSize, IntPtr pArguments); // an overload to the FormatMessage call [DllImport("kernel32.dll", SetLastError = true)] static extern uint FormatMessage(uint dwFlags, IntPtr lpSource, uint dwMessageIg, uint dwLanguageId, ref IntPtr lpBuffer, uint nSize, string[] arguments); [DllImport("kernel32.dll", SetLastError = true)] static extern uint FormatMessage( uint dwFlags, IntPtr lpSource, uint dwMessageId, uint dwLanguageId, [Out] StringBuilder lpBuffer, uint nSize, string[] Arguments); [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr LocalFree(IntPtr hMem); // // from header files const uint FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100; const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200; const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; const uint FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000; const uint FORMAT_MESSAGE_FROM_HMODULE = 0x00000800; const uint FORMAT_MESSAGE_FROM_STRING = 0x00000400; static string FormatNativeMessage(string formatExpression, string[] formatArgs) { try { StringBuilder msgBuilder = new StringBuilder(101); IntPtr formatPtr = Marshal.StringToHGlobalAnsi(formatExpression); // what is those global alloc and what is the local alloc? // Must specify the FORMAT_MESSAGE_ARGUMENT_ARRAY flag when pass an array uint length = FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, formatPtr, 0, 0, msgBuilder, 101, formatArgs); if (length == 0) { FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, IntPtr.Zero, (uint)Marshal.GetLastWin32Error(), 0, msgBuilder, 101, null); Console.WriteLine("Error:" + msgBuilder.ToString()); } else { Console.WriteLine("Format result : " + msgBuilder.ToString() + ", Length:" + length.ToString()); return msgBuilder.ToString(); } } catch (Exception ex_) { Console.WriteLine(ex_.ToString()); } return null; } // normally you can do is just to throw out the Win32Exception with the error code as arguments static string FormatLastWin32Message(uint error) { IntPtr lpMsgBuffer = IntPtr.Zero; uint dwFlags = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, IntPtr.Zero, (uint) error, 0, // default language ref lpMsgBuffer, 0, IntPtr.Zero); if (dwFlags == 0) { // handle the error int le = Marshal.GetLastWin32Error(); return null; } else { string sRet = Marshal.PtrToStringAnsi(lpMsgBuffer); LocalFree(lpMsgBuffer); // return the buffer return sRet; } } static string FormatLastWin32Message() { int nLastError = Marshal.GetLastWin32Error(); return FormatLastWin32Message((uint) nLastError); }And below is the drive code , which demonstrate the use of it.
static void Main(string[] args) { string formatExpression = "%1,%2%!"; // it accepts different set of format specifiers.... string[] formatArgs = new[] { "Hello", "World" }; string formattedMessage = FormatNativeMessage(formatExpression, formatArgs); if (!string.IsNullOrEmpty(formattedMessage)) { Console.WriteLine("The fomatted message is {0}", formattedMessage); } var formattedLastWin32ErrorMsg = FormatLastWin32Message(); if (!string.IsNullOrEmpty(formattedLastWin32ErrorMsg)) { Console.WriteLine("LastWin32Message : {0}", formattedLastWin32ErrorMsg); } }