Saturday, November 29, 2014

Avoid alphabetical reading of Windows environment variables



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.


Answer



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.



No comments:

Post a Comment

linux - How to SSH to ec2 instance in VPC private subnet via NAT server

I have created a VPC in aws with a public subnet and a private subnet. The private subnet does not have direct access to external network. S...