Open regedit.exe, navigate to HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment. Create two environment variables:

Name   Type            Data
-----  --------------  -----------
zbar   REG_SZ          water
zfoo   REG_EXPAND_SZ   %zbar%

Open new cmd.exe, powershell.exe or whatever. These variables are missing. Make LogOff, then LogOn. In cmd.exe window type echo %zbar% - water is displayed. Type echo %zfoo% and %zbar% is displayed, but I expect to see expanded value - water.

And now. Open Windows Environment Variables dialog. Alter or create any variable (for example zzz=zzz). Reopen cmd.exe and type echo %zfoo% - now you see water!

Actually, I am creating these variables with PowerShell script. But all this script does is described registry manipulations.


  1. How to force zfoo variable to have a correct value without that magic with opening Windows Environment Variables dialog and altering some variables? Maybe I should call some API, something like [Microsoft.Win32.Registry]::Refresh()?
  2. It is possible to make these variables visible to users without need for LogOff/LogOn operations? If I edit user-level environment variables (also in registry) they are immediately available, but with global - they are not.



You need to broadcast the WM_SETTINGCHANGE Message.

Remember: You're not actually setting any environment variables of any form when you modify the registry. Environment variables are part of each individual process' memory space, with each process having its own set. They don't live in the registry. You are changing a template. You need to persuade the programs that set actual environment variables to re-read the template and set their environments accordingly. You do that by broadcasting a Windows message that tells any interested parties that the template in the registry has changed. Microsoft Windows Explorer is one such interested party, and modifies its own environment variables whenever it hears that the template has changed. These modifications are then inherited in the normal way by any new process that Explorer spawns.

  • 1
    Yes, you need to broadcast WM_SETTINGCHANGE (though only windows that specifically handle it will actually pick up the changes), but also, note that even then, when you make a(ny) change, any variables that contain other variables will stop getting expanded until you reboot (including ones that already existed). It’s a weird bug (in at least XP and 7) that I’ve banged my head against countless times. – Synetech May 25 '11 at 1:22
  • For a source code example in C#, see also here @ StackOverflow. – Matt Oct 16 '18 at 8:56

You can use SETX, it will broadcast WM_SETTINGCHANGE after setting variable:


Or, if you insist to enter the variables into the registry, you can have SETX set a variable that already exists, in order to broadcast the registry change:


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.