How to Use Formatmessage() Properly in C++

How should I use FormatMessage() properly in C++?

Here's the proper way to get an error message back from the system for an HRESULT (named hresult in this case, or you can replace it with GetLastError()):

LPTSTR errorText = NULL;

FormatMessage(
// use system message tables to retrieve error text
FORMAT_MESSAGE_FROM_SYSTEM
// allocate buffer on local heap for error text
|FORMAT_MESSAGE_ALLOCATE_BUFFER
// Important! will fail otherwise, since we're not
// (and CANNOT) pass insertion parameters
|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, // unused with FORMAT_MESSAGE_FROM_SYSTEM
hresult,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&errorText, // output
0, // minimum size for output buffer
NULL); // arguments - see note

if ( NULL != errorText )
{
// ... do something with the string `errorText` - log it, display it to the user, etc.

// release memory allocated by FormatMessage()
LocalFree(errorText);
errorText = NULL;
}

The key difference between this and David Hanak's answer is the use of the FORMAT_MESSAGE_IGNORE_INSERTS flag. MSDN is a bit unclear on how insertions should be used, but Raymond Chen notes that you should never use them when retrieving a system message, as you've no way of knowing which insertions the system expects.

FWIW, if you're using Visual C++ you can make your life a bit easier by using the _com_error class:

{
_com_error error(hresult);
LPCTSTR errorText = error.ErrorMessage();

// do something with the error...

//automatic cleanup when error goes out of scope
}

Not part of MFC or ATL directly as far as I'm aware.

Why does FormatMessage only create partial messages for ERROR_SYSTEM_PROCESS_TERMINATED and ERROR_UNHANDLED_EXCEPTION system errors?

The messages you mention (ERROR_UNHANDLED_EXCEPTION and ERROR_SYSTEM_PROCESS_TERMINATED) have printf-style inserts (%08x). However, FormatMessage uses %0 to terminate a message.

My guess is that there's another avenue where these messages are returned by the system with the printf-style placeholders already populated; these messages, in their raw form, are not meant to be handled by FormatMessage.

Given that these messages contain the text (Fatal System Error) or (Application Error), it is not altogether surprising that Windows handles these message specially.

FormatMessage with placeholders

Try adding FORMAT_MESSAGE_IGNORE_INSERTS to the flags.

FormatMessage to a different language

Basically MUI stands for multilingual user interface. These are language packs. In windows one won't get them by default. Instead they have to install

Below link helps you regarding procurement.

https://support.microsoft.com/en-us/help/14236/language-packs

By default the above page displays for windows 10 . there is a drop down option to select for the other versions of windows.

If you have difficulty with above link, search in google for MUI language pack for windows 10 or any other version.

How to add message to message table with ID greater than 0x20000000 (bit 29 set)?

You need to use the -c argument for mc.exe - this will make it set the "Customer code flag" (bit 29) for all message IDs.

The actual message ID value you specify in the message text file must fit in 16 bits (so in the above example, you would just specify MessageId=1 and with the -c flag, mc.exe would turn this into 0x20000001).

Getting the Windows System Error Code title/description from its hex number

I'm not sure if there's a niifty .NET wrapper, but you could call the FormatMessage API using P/Invoke.

See this answer for how it would normally be called from native code. Though the question refers to grabbing error codes from HRESULTs, the answer also applies for retreiving codes from the regular OS error codes coming from GetLastError/GetLastWin32Error).

EDIT: Thanks Malfist for pointing me to pinvoke.net, which includes alternative, managed API:

using System.ComponentModel;

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

Is there a way to get the string representation of HRESULT value using win API?

You can use _com_error:

_com_error err(hr);
LPCTSTR errMsg = err.ErrorMessage();

If you don't want to use _com_error for whatever reason, you can still take a look at its source, and see how it's done.

Don't forget to include the header comdef.h



Related Topics



Leave a reply



Submit