Oceania is at war with WM_SETTINGCHANGE; Oceania has always been at war with WM_SETTINGCHANGE

by Michael S. Kaplan, published on 2008/07/01 03:01 -04:00, original URI: http://blogs.msdn.com/b/michkap/archive/2008/07/01/8675015.aspx

The question that came to a managed code alias was easy enough to see:

How can I either (1) detect that a system environment variable has changed, or (2) get the current system-wide setting of an environment variable (not necessarily the value of the variable as it was set when my app was launched)?

Windows apps are notified via the WM_WININICHANGE, but I’m looking for a way to do it in a .NET app.

I'll deal with the second paragraph first -- why is it that everyone wants to do stuff the ".NET way" even hen asking a purely Windows question that even when there is a 100% managed way one has to realize that under the covers there will be numerous native things going on, whether pinvokes or other. Is this a naive code purity thing, a desire to eat the steak without thinking about the cow?

Okay, we'll move past that. Someone ignored the manged-only piece and suggested they take a look at the WM_SETTINGCHANGE message, but there was a less than positive response to that idea:

Thanks for the response.

I don’t know how the... link will help---when I change an environment variable, the WM_WININICHANGE message is sent to all top-level windows (tested on Vista), and not the WM_SETTINGCHANGE message.

Also, one question I forgot to ask is: if I only can capture some notification that the system environment changed, then that’s not enough; how do I get the contents of the new system environment?

I laughed when I saw that one, I mean what with the following defined in winuser.h since the late 90's:

#define WM_WININICHANGE                 0x001A
#if(WINVER >= 0x0400)
#endif /* WINVER >= 0x0400 */


Like that old Bill Tush skit with the teenagers who argue because one loves the words but hates the lyrics, while the other insists that the lyrics are awesome but the words suck.

Only not contrived!

In fairness, the WM_WININICHANGE message and the WM_SETTINGCHANGE message don't go out of their way to help here -- they in fact seem designed to do the opposite, really.

You know, like they put on their Eagles hats and sing "Relax, said the night man, we are programmed to deceive" without realizing they have the words wrong; they don't realize the topics are writing checks that the header files can't cash....

Whether one looks at the amusing text in the WM_WININICHANGE message:

An application sends the WM_WININICHANGE message to all top-level windows after making a change to the WIN.INI file. The SystemParametersInfo function sends this message after an application uses the function to change a setting in WIN.INI.

Note  The WM_WININICHANGE message is provided only for compatibility with earlier versions of the system. Applications should use the WM_SETTINGCHANGE message.

With a claim that the wParam is not used and just a small message about the lParam:

A pointer to a string containing the name of the system parameter that was changed. For example, this string can be the name of a registry key or the name of a section in the Win.ini file. This parameter is not particularly useful in determining which system parameter changed. For example, when the string is a registry name, it typically indicates only the leaf node in the registry, not the whole path. In addition, some applications send this message with lParam set to NULL. In general, when you receive this message, you should check and reload any system parameter settings that are used by your application.

All of which is most amusing when you look at the very different text in the WM_SETTINGCHANGE message that gives numerous details about the values of both parameters.

Though ultimately the funniest part being the requirements for both functions:

Client Requires Windows Vista, Windows XP, or Windows 2000 Professional.
Server Requires Windows Server 2008, Windows Server 2003, or Windows 2000 Server.

This is something that makes very little sense given just the header file alone, let alone the pragmatic knowledge between the two topics and the past knowledge of many a Windows developer. :-)

The language of the documentation, it can be its own dialect of English at times....


No Unicode character wanted to support this blog except some of the old ones that were removed from Unicode as a part of the 10646 merger

# John Cowan on 1 Jul 2008 9:49 AM:


Are there really any such characters?  I know we picked up a bunch from the failed first DIS, but I didn't think we *lost* any.

# Michael S. Kaplan on 1 Jul 2008 9:56 AM:

Well, we got them back later -- like the original Tibetan, described here....

# andy vt on 1 Jul 2008 12:15 PM:

The ".NET way" means that you write less code, which means you support less code.

Why go through the effort of rolling your own pinvoke solution when someone did it for you already?  

# Skip on 1 Jul 2008 12:37 PM:

Well I can certainly understand not wanting to have to figure out the mechanics of pinvoke if you're someone who was never exposed to the underlying c.   Honestly, it's not something I'd want a large chunk of the people I've worked with in .net coding over the last few years doing.

But in any case, shouldn't you just be able to use System.Windows.Forms.NativeWindow to do this fairly easily?

# Michael S. Kaplan on 1 Jul 2008 12:46 PM:

After meeting and discussing technical issues with people like Anthony and Brian Josh and Kim, I'm happy to use the code they have written -- if it does what I am looking for.

But since I usually write native code, I am just as happy to provide my own abstractions, sometimes even moreso!

# Karellen on 1 Jul 2008 4:45 PM:

'why is it that everyone wants to do stuff the ".NET way" even hen asking a purely Windows question'

Uh, maybe it's because it might not be a purely Windows question, because .NET apps are supposed to be portable to other .NET implementations, and because the author might be trying to write an app they can deploy on MS.NET and Mono?

# Ruben on 1 Jul 2008 4:56 PM:

It seems WM_WININICHANGE already triggers System.Win32.SystemEvents.UserPreferenceChanged. So no need to use P/Invoke or NativeWindow. And, much like WM_WININICHANGE, it doesn't tell you much more than Category = General.

# Yuhong Bao on 8 Jul 2008 2:04 AM:

"Though ultimately the funniest part being the requirements for both functions:

   Client Requires Windows Vista, Windows XP, or Windows 2000 Professional.

   Server Requires Windows Server 2008, Windows Server 2003, or Windows 2000 Server.

This is something that makes very little sense given just the header file alone, let alone the pragmatic knowledge between the two topics and the past knowledge of many a Windows developer. :-)"

Dig out the Platform SDK for Windows Server 2003 SP1's documentation. Current versions has gotten rid of some of the references to versions of Windows prior to Windows 2000. Talk to the Windows SDK team for more on this.

referenced by

2008/08/13 Migrating docs forward vs. moving 'em forward

go to newer or older post, or back to index or month or day