0

Normally, if I define one User Windows 10 environment variable (var 1) in terms of another (var 2), var 2 should precede var 1 in alphabetical order for it to work. This is identified here, e.g.

For instance, in the window

enter image description here

this

APYTHONDIR  ->  C:\Users\user1\myprogs
PATH  ->  %APYTHONDIR%

works, but this

PYTHONDIR  ->  C:\Users\user1\myprogs
PATH  ->  %PYTHONDIR%

does not.

Is there any way of avoiding it? Working around it?

I mean to get a solution that functionally works the same as if the variables were defined via registry (or Control Panel).

I can always use naming to ensure "nested" definitions follow alphabetical order. This is not what I want.

I thought about setting them in the desired order in a startup batch file (autoexec.nt, or whatever is current). I am not sure if this would work for any application requiring the environment variables. E.g., octave symbolic integration needing to find python somewhere in the PATH, with the directory in the PATH being added in this way.

EDIT As per the answers by harrymc and myself, and following discussion, this is what I tried:

  1. Creating a file set_env_vars.bat in an arbitrary directory, and set a shortcut to it in %USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup.

  2. Adding a line set /P PTEST=Enter value for PTEST in set_env_vars.bat to make sure the file is being read during logon.

  3. Logging off and on. I verified that set_env_vars.bat is read.

Then, I added lines

set ZTEST_DIR=C:\ztest
set YTEST_DIR=%ZTEST_DIR%;C:\ytest

to set_env_vars.bat. Plus log off / log on. This didn't give me vars ZTEST_DIR and YTEST_DIR in my environment.

Then, I replaced those with lines

setx ZTEST_DIR C:\ztest
set /P WAITING_DUMMY=Enter value for WAITING_DUMMY   
setx YTEST_DIR %ZTEST_DIR%;C:\ytest

in set_env_vars.bat. (The second line to try giving time to the system to set the first var). Plus log off / log on. This gave me vars

YTEST_DIR=;C:\ytest
ZTEST_DIR=C:\ztest

in my environment.

  • autoexec.bat was used with MS-DOS, Windows 3.x and Windows 95. It no longer exists since Windows NT. – harrymc Jul 26 at 11:17
  • Note also that alphabetical order is not needed for it to work. Test and see. – harrymc Jul 27 at 12:55
  • 1
    @harrymc - I am posting because that is what I observed. And the link provided states the same. Do you not see such behaviour? – sancho.s Reinstate Monica Jul 27 at 15:56
  • What are you trying to do? Your question is unclear. Why does the order of the environment variables matter? – LawrenceC Jul 31 at 15:17
  • @LawrenceC - I cannot figure out how to make the question any clearer... that is what I want to do. As for why I want to do that: I mean to have uniform naming of several variables across Win and Linux systems. In the latter, defining one environment variable in terms of another (e.g., in .bashrc) is irrespective of alphabetical order; it depends on the order of execution of variables definition commands. The question shows that this is not that simple to achieve in Win. I can always use naming to ensure "nested" definitions follow alphabetical order. This is not what I want. – sancho.s Reinstate Monica Jul 31 at 17:57
2

If you do set "a=x%b%y", then a is defined exactly like that, and %b% will only be expanded when required. This is why alphabetical order has no importance. Variables are substituted when their value is required, and PATH is an example of a value that is immediately required.

To automate setting environment variables, put the SET commands in a batch file (.bat) and copy the file to the Startup folder.

Your personal startup folder should be C:\Users\<user name>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup, while the All Users startup folder should be C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup.

Question: What am I doing below that is different than what you do? You could show us a similar screenshot if you are getting different results.

enter image description here


As regarding the example you have posted, the results are as expected. You have used the setx command, which sets environment variables for the user in the registry, but not in the local environment. You would need to start a new Command Prompt from the desktop to benefit from that variable.

The important point here is that setx works on the registry, but that does not cause the local environment to be re-evaluated. The environment is built only once, when a process is launched, then stays the same all through execution (unless modified locally by the process itself). Any child started by a parent process will inherit its parent's environment, so no reference is made in that case to the registry.

The demo below demonstrates the problem: The variable is set in the above Command Prompt, but doesn't have a local value. The lower Command Prompt is then started from the desktop, and it does have that value.

enter image description here

  • I have posted an answer. With reference to it, I was using method 1; you propose method 3, which is per se not sufficient (the automated definition is missing). Besides, I do not know the difference, if any, when using quotes or not, in set commands. – sancho.s Reinstate Monica Aug 1 at 2:05
  • Quotes in SET are usually optional, but without them one may encounter weird effects in batch files. I have added a part about automation. – harrymc Aug 1 at 4:55
  • @sancho.s: Is for you my answer is now complete? – harrymc Aug 4 at 19:35
  • Maybe, I still didn't have time to try it. Will do it before the bounty expires. – sancho.s Reinstate Monica Aug 5 at 1:30
  • It did not work. I posted what I tried as an edit to the OP, it wouldn't fit in a comment. You may try it yourself, I bet you find an answer! – sancho.s Reinstate Monica Aug 7 at 8:55
0

In summary:

  1. Setup file setvars.cmd (the name is arbitrary) in directory %USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup, or put setvars.cmd elsewhere and set a shortcut to it from there.

  2. In that file, use (e.g.)

    setx DIR2 C:\dir2
    set DIR2=C:\dir2
    setx DIR1 %DIR2%;C:\dir1
    set DIR1=%DIR2%;C:\dir1
    

Tested and it works.


tl;dr

There seem to be at least 3 alternative ways to define user environment variables:

  1. Via Control Panel.
    Right-click computer -> Properties -> Advanced system settings -> Environment Variables -> New for User variables for USER1 -> Type in Name and Value for the variable -> Ok.
    "Nested" usage of variables is read in alphabetical order.
    Variables are also displayed in alphabetical order.

  2. Via registry editing of HKEY_CURRENT_USER\Environment.
    Windows key -> reged -> Goto HKEY_CURRENT_USER\Environment in the address bar -> Edit -> New -> REG_EXPAND_SZ -> Type Name -> Right click on added name -> Modify -> Type Value -> Ok.
    "Nested" usage of variables is read in the order they were defined.
    Variables are displayed in alphabetical order, only for convenience.
    This answers the question, in principle. But if "nested" definitions that do not follow alphabetical order were used, one is "banned" from using the Control Panel method ever again, otherwise it enforces alphabetical order reading and messes up the definitions.

  3. Via command line / batch file / autoexec.
    As detailed below. Helped by this answer, with the added use of SETX var value instead of only SET var=value.
    "Nested" usage of variables is read in the order they were defined.
    And with proper automation, this is done at each logon, so using the Control Panel way would only possibly mess up "nested" definitions for the current session. This is probably the best combination.

Note that to avoid having to log off to reread variables, one can use this, or refreshenv.

Detail of method 3: The proper way of achieving the objective of the OP (get a solution that functionally works the same as if the variables were defined via registry (or Control Panel), but avoiding alphabetical ordering) is:

  1. Using a .bat (or, better, a .cmd) file, read during logon (method 3), say, setvars.cmd.

  2. In that file, using setx to set environment variables at the registry level (e.g., var2). This does not update the local environment.

  3. To be able to use "nested" variable definitions that endure for the windows session (e.g., var1 in terms of the value of var2), one needs var2 to be also defined in the process spawned by setvars.cmd. According to item 2 above, this is not accomplished by setx. For that, one would add a set line corresponding to each setx line. With this, the same environment is obtained in the registry and in the local process. Alternatively, one may try using REG query HKCU\Environment /V ... chained with other commands (as used, e.g., in refreshenv), but I did not pursue this. If the Control Panel way is ever used, it can mess up nested definitions that do not follow alphabetical order. This can be overcome by simply executing again setvars.cmd.

  • Method 1 only displays in alphabetical order for readability. Method 2&3 are the same in effect for setx. Set only works on local environment so doesn't relate. – harrymc Aug 8 at 16:11
  • @harrymc - I did not get whether you mean the proposed solution works or not. Plus, as commented before, method 1 displays in alphabetical order, and applies settings in alphabetical order as well. That is what I see, and what others reported as well. I wouldn't know if your system behaves differently, and in that case what produces the difference. Method 2 displays in alphabetical order, and applies settings in the order definitions were set. – sancho.s Reinstate Monica Aug 9 at 15:56

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.