SendMessageTimeout problems & the solution - Programmer

This is a discussion on SendMessageTimeout problems & the solution - Programmer ; How to change environment variables and have those environment variables show up in new processes. If you use the advanced control panel it works, I couldn't get it to work myself programmatically. This problem was Posted by Matt Gerrans 2 ...

+ Reply to Thread
Results 1 to 4 of 4

Thread: SendMessageTimeout problems & the solution

  1. SendMessageTimeout problems & the solution

    How to change environment variables and have those environment
    variables show up in new processes. If you use the advanced control
    panel it works, I couldn't get it to work myself programmatically.

    This problem was Posted by Matt Gerrans 2 years ago to this newsgroup.
    I wanted to answer it so that the answer is archived, since I just
    spent 4 hours figuring it out ... What a waste of time!

    Read the article below first to see what the problem is.

    I ended up writing a windows program to intercept the WM_ messages and
    see exactly what the difference was between the control panel and my
    code, and the solution is, instead of (what Microsoft said in the
    below knowledge base article):

    SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)
    "Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue);

    Do:

    SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)
    L"Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue);

    The "L" is important, otherwise the String is not set to a wide string
    and the shells and such ignore it! Without the L to output a wide
    string, a garbage string is sent to apps, which the apps ignore.

    Silly me for believing that a code example written by MICROSOFT on
    their own OS would actually work. That assumption cost me most of the
    time

    Hopefully saving future generations some headaches,

    -Eric

    From: Matt Gerrans (mgerrans@mindspring.com)
    Subject: Setting System Environment Variables in XP
    This is the only article in this thread
    View: Original Format
    Newsgroups: comp.os.ms-windows.programmer.misc
    Date: 2002-06-22 13:07:10 PST

    I'm trying to find the trick to setting a system environment variable
    the
    sames way the "Environment Vairables" dialog does, without a reboot.
    If I
    use the dialog to set a variable and then open a new command shell
    window,
    the variable is set, as expected. If I follow the instructions
    (below)
    given on MSDN to do it programmatically, it doesn't quite work; a new
    command shell will not see the variable, but if I open the Environment
    Variables dialog, it is there and if I then click OK in the dialog and
    open
    a new command prompt, it does appear. That tells me that the dialog
    is
    doing a little more than broadcasting the settings changed message --
    but
    what?

    Th article on MSDN
    (http://msdn.microsoft.com/library/de...-us/dllproc/pr
    othred_89f7.asp) says this:
    "Calling SetEnvironmentVariable has no effect on the system
    environment
    variables. The user can add or modify system environment variables
    using the
    Control Panel. To programmatically add or modify system environment
    variables, add them to the
    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Contro l\Session
    Manager\Environment registry key, then broadcast a WM_SETTINGCHANGE
    message.
    This allows applications, such as the shell, to pick up your updates."

    So I did this:
    //...
    String subkey = "SYSTEM\\CurrentControlSet\\Control\\Session
    Manager\\Environment";
    TRegistry *reg = new TRegistry();
    reg->RootKey = HKEY_LOCAL_MACHINE;
    if( reg->OpenKey( subkey, false ) )
    reg->WriteString( EditName->Text, EditValue->Text );
    delete reg;
    SendMessageTimeout( HWND_BROADCAST, WM_SETTINGCHANGE, 0,0,0, 1000,
    NULL );
    SendMessageTimeout( HWND_BROADCAST, WM_WININICHANGE,
    0,(LPARAM)"Environment",0, 1000, NULL );
    //...

    Maybe this works as documented for NT and/or Win2k (I haven't tried my
    code
    on those, yet), but it doesn't seem to be enough XP. I threw in the
    WM_WININICHANGE broadcast also, in the hopes that it would do the
    trick, but
    no dice. I also tried sending the messag directly to the desktop
    window,
    to no avail. Anybody know what tricks that dialog is doing? It is
    clearly doing more than just the broadcast message -- maybe it is
    sending
    the message directly to some particular window?

    - mfg

  2. Re: SendMessageTimeout problems & the solution

    On 10 Nov 2004 23:50:55 -0800, eric@webmethods.com (Eric van
    Bezooijen) wrote:
    >SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)
    >L"Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue);
    >
    >The "L" is important


    actually it should be

    SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)
    TEXT("Environment"), SMTO_ABORTIFHUNG, 5000, &dwReturnValue);

    The code in the KB article is correct for ANSI programs. The code
    you posted is correct for UNICODE programs. Remember, there are
    two SendMessageTimeout functions, one ANSI and one UNICODE. You
    have to pass the parameters appropriate for the version you are
    using.



  3. Re: SendMessageTimeout problems & the solution

    Raymond Chen wrote in message news:...
    > On 10 Nov 2004 23:50:55 -0800, eric@webmethods.com (Eric van
    > Bezooijen) wrote:
    > >SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)
    > >L"Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue);
    > >
    > >The "L" is important

    >
    > actually it should be
    >
    > SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)
    > TEXT("Environment"), SMTO_ABORTIFHUNG, 5000, &dwReturnValue);
    >
    > The code in the KB article is correct for ANSI programs. The code
    > you posted is correct for UNICODE programs. Remember, there are
    > two SendMessageTimeout functions, one ANSI and one UNICODE. You
    > have to pass the parameters appropriate for the version you are
    > using.


    You are correct. I missed one line in the description of the
    SendMessageTimeout routine: "Unicode Implemented as ANSI and Unicode
    version". I assumed it was hardwired to one or the other since I
    didn't see a SendMessageTimeoutW/A anywhere. Either way, the code
    example by Microsoft is still incorrect.

    -Eric

  4. Re: SendMessageTimeout problems & the solution

    Well, it seems as if the documentation is not quite detailed, regards when what is actually neccesary.

    I had the same problem as described in the previous posts, when I tried to run the code below. That code compiles as a console application:

    // compile with: cl user32.lib touchenv.cpp
    #include
    #include

    int _tmain(int argc, _TCHAR* argv[])
    {
    DWORD dwReturnValue;
    // If this is to work in a console application , the "Environment" string
    // needs to be Unicode, use L"Environment" instead
    LRESULT error1 = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
    (LPARAM) L"Environment", SMTO_ABORTIFHUNG,
    5000, &dwReturnValue);

    return dwReturnValue;
    }

    So I changed to L"Environment" as described, and everything worked. Nice.
    Now, I did not want this little application to pop up a commad window when executed from explorer etc, so I rewrote a bit:

    // compile with cl user32.lib touchenv.cpp -link -SUBSYSTEM:WINDOWS
    #include
    #include

    //int _tmain(int argc, _TCHAR* argv[])
    int APIENTRY _tWinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine,
    int nCmdShow)
    {
    DWORD dwReturnValue;
    // If this is to work in a console application , the "Environment" string
    // needs to be Unicode, use L"Environment" instead
    LRESULT error1 = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
    (LPARAM) "Environment", SMTO_ABORTIFHUNG,
    5000, &dwReturnValue);

    return dwReturnValue;
    }

    And then I had to remove the L in front of "Environment" to make it work. So basically it is all a matter of assumptions made when the Microsoft doc is written. And it notoriously difficult to know what assumptions a certain feature relies upon.

    Anyway both of the above code snippets works compiled on MSVC 2008.

    Jacob

+ Reply to Thread