Welcome to MSDN Blogs Sign in | Join | Help

Why can't I get FormatMessage to load my resource string?

A common mistake I see is people confusing message tables with string resources. This basically shows up in one place: FormatMessage.

The folks who were designing Win32 decided that plain string resources weren't fancy enough, so they invented message tables, which is just another way of storing strings in resources. Why string resources weren't good enough I don't know.

The FormatMessage function accepts a message number, which is looked up in a message table, not in a string resource. In other words, if you have something like this:

#define IDS_MYMESSAGE 100

STRINGTABLE BEGIN
    IDS_MYMESSAGE "Hello, %1"
END

TCHAR szBuffer[256];
FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, g_hInstance,
              IDS_MYMESSAGE, 0, szBuffer, 256, Arguments);

the call to FormatMessage will fail because you passed in a string resource identifier, not a message identifier. Since nobody actually uses message tables, you almost certainly want to pass the FORMAT_MESSAGE_FROM_STRING flag.

TCHAR szMessage[256];
LoadString(g_hInstance, IDS_MYMESSAGE, szMessage, 256);
TCHAR szBuffer[256];
FormatMessage(FORMAT_MESSAGE_FROM_STRING, szMessage,
              IDS_MYMESSAGE, 0, szBuffer, 256, Arguments);

The only place you will normally want to format a message from a message table is when you want to access the system message table to get the text associated with an error code. (But don't forget the FORMAT_MESSAGE_IGNORE_INSERTS flag!)

Published Friday, February 29, 2008 7:00 AM by oldnewthing
Filed under:

Comments

# re: Why can't I get FormatMessage to load my resource string?

Friday, February 29, 2008 10:24 AM by Ian

One thing I've noticed in message tables that string resources don't apparently offer is the option to build the message table either as ANSI. When you have a very large number of messages and you don't need non-ANSI characters it can be a significant space-saver.

Alarm bells might ring over using ANSI encoding - what if you need some non-ANSI characters in the future? Fortunately, all you have to do is flip the flag in the message compiler. FormatMessage() checks the resource to see whether it needs to do the ANSI to Unicode conversion and does the right thing. You can even have a message DLL for one language in ANSI and one for another language in Unicode.

Incidently, hyperbole aside, one place where you are pretty-much forced into using message tables instead of string resources is in Windows Services, or for that matter any application that logs messages to the Windows Event Log.

# NT event log

Friday, February 29, 2008 10:49 AM by Nathan_works

You can always do the subtle trick that .NET does to write to the event log -- set all your message strings to "%1", so that you can call the WriteEvent() function with only your string.

Though that puts hard coded strings all over your code, rather than centralized in the message catalog.

# re: Why can't I get FormatMessage to load my resource string?

Friday, February 29, 2008 11:32 AM by Gabe

I don't know the structure of message tables, but judging by the name it's likely that somebody had the idea that it was an optimization over regular string resources. Odds are the difference now is infitessimal, but on 8MB 386s it might have mattered.

# re: Why can't I get FormatMessage to load my resource string?

Friday, February 29, 2008 12:29 PM by Mike Dimmick

As Nathan_Works alludes to, you need to support message tables to write to the event log. You're supposed to translate your messages into whatever language your customer might want to read the event log in, and use substitutions - positional substitutions - to include the actual non-translated data for the event.

The .NET Framework does have a generic "%1" for people who understandably don't want to have to build a message table or understand how the resource compiler works.

# re: Why can't I get FormatMessage to load my resource string?

Friday, February 29, 2008 12:31 PM by Anon

Assuming these messages are the same as those read by the event viewer, then....

It might be worth mentioning that a message DLL, is read by the event viewer and not the event logging service.

If you're a dimwit like myself, you'll be wondering why your changes to the DLL don't show up, and thinking that you'll have to reboot the machine when you can't restart the event logging service.

In my dimwit kind of way I'd say that messages do make some sense when you're writing a service, although personally I'd be happy just to dump ASCII UK/English in there.

# re: Why can't I get FormatMessage to load my resource string?

Friday, February 29, 2008 2:20 PM by J. Passing

I assume the main reason for the co-existance of stringtables and messagetables is that they have different origins. Message tables are used for event logging, which is a concept of native NT and also supported by kernel APIs. Judging from the fact that LoadString and friends are implemented in user32.dll, stringtables seem to be a mere Win32 concept.

# re: Why can't I get FormatMessage to load my resource string?

Friday, February 29, 2008 3:46 PM by dave

Message tables are closely related in essence to the VMS message system, just as the layout of NT status codes is closely related to the layout of VMS status codes.

There also seems to be a bias in message tables to the emitter of a status code not being the app that will eventually display the message (i.e., the system-call model), whereas the bias in string resources appears to be that emitter and displayer are either the same, or closely related.

# re: Why can't I get FormatMessage to load my resource string?

Friday, February 29, 2008 3:46 PM by dave

Message tables are closely related in essence to the VMS message system, just as the layout of NT status codes is closely related to the layout of VMS status codes.

There also seems to be a bias in message tables to the emitter of a status code not being the app that will eventually display the message (i.e., the system-call model), whereas the bias in string resources appears to be that emitter and displayer are either the same, or closely related.

# re: Why can't I get FormatMessage to load my resource string?

Friday, February 29, 2008 5:30 PM by Tom

I've always thought the message tables were a bit peculiar, if only because the only place I saw them used was in the event viewer.  One of the advantages of using the message table over string table is that, if the user changes the default Windows language, the message can be automatically formatted in the new language.  In fact, this technique is important enough that I'm planning on doing something similar with engineering units.  I need to write sensor data to message logs that the user can select to see in metric or English units.

[You can do the language-switching with string tables too. See the LANGUAGE keyword. -Raymond]

# Origins of message tables

Saturday, March 01, 2008 3:31 PM by John

I'm 80% sure that message tables came to Windows from OS/2, which inherited them from LAN Manager.  Maybe Larry Osterman could provide a history lesson.

# re: Why can't I get FormatMessage to load my resource string?

Saturday, March 01, 2008 8:48 PM by LarryOsterman

John, I don't remember - I first encountered them in NT 3.1.

# re: Why can't I get FormatMessage to load my resource string?

Sunday, March 02, 2008 6:00 PM by steveg

> Maybe Larry Osterman could provide a history lesson.

I was hoping for something on the Crimean war. Maybe next time.

# re: Why can't I get FormatMessage to load my resource string?

Monday, March 03, 2008 5:55 AM by Stefan Kuhr

I think the biggest advantage in message tables over stringtables is that using FormatMessage, you can specify a language ID. You can't do that with the LoadString API. In order to achieve something similar, you have to use low-level resource APIs in order to read stringtable resources for a given language ID. Additionally, using message tables along with the message compiler gives a nice mechanism of creating custom error codes and automatic resolution into human readable strings using FormatMessage. That's why I really like message tables :-)

# re: Why can't I get FormatMessage to load my resource string?

Monday, March 03, 2008 9:21 AM by Kevin Eshbach

I wonder if they weren't created to get around the 64K length limitation of a string in a string table.

New Comments to this post are disabled
 
Page view tracker