7

I am looking for a way on Windows how to set an environment variable dependent on another one. In my case, I want to add the new path to PYTHONPATH. Let's say, that there is an existing environment variable

%INSTALLATION_DIR% = D:\Programs\MyProject

The easiest way to do that would be:

SETX PYTHONPATH "%PYTHONPATH%;%INSTALLATION_DIR%\Utility\Scripts"

But then, %INSTALLATION_DIR% is directly replaced by D:\Programs\MyProject, so PYTHONPATH is not updated if %INSTALLATION_DIR% changes.

Is there a way to write the text %INSTALLATION_DIR% into an environment variable, without evaluating the variable directly?

If possible, I want to do that in an automated way (so using the console, powershell or python), as a want to write a script which adds a list of paths to PYTHONPATH.

golden96371
  • 350
  • 6
  • 19
  • guess you are looking for delayedexpansion. kindly refer https://stackoverflow.com/questions/10558316/example-of-delayed-expansion-in-batch-file – user2648008 Jun 13 '19 at 07:33
  • 1
    Thank you for the link, but this is not that I'm looking for. The problem is not that the variables can change during the script, but that I want to use the text '%INSTALLATION_DIR%' instead of the value of this environment variable. – golden96371 Jun 13 '19 at 07:49

2 Answers2

2

I just found the solution. If the name of the environment variable is written in quotes, it will not be evaluated.

SETX PYTHONPATH "%PYTHONPATH%;%"INSTALLATION_DIR"%\Utility\Scripts"

golden96371
  • 350
  • 6
  • 19
  • 1
    Note that `INSTALLATION_DIR` should be a simple value that doesn't depend on other environment variables. In the registry it should be a `REG_SZ`, while `PYTHONPATH` will be a `REG_EXPAND_SZ`. Windows takes care to load all `REG_SZ` values before `REG_EXPAND_SZ` values, so it's always okay for the latter to depend on the former. – Eryk Sun Jun 13 '19 at 11:15
  • 1
    Note also that using setx.exe by itself expands the current `PYTHONPATH` value, which may depend on other variables. To prevent this you need to get the unexpanded value via reg.exe. – Eryk Sun Jun 13 '19 at 11:18
  • 1
    Also, it's documented by example in the help that setx.exe will replace "~" with "%" to get around shell expansion. – Eryk Sun Jun 13 '19 at 11:21
  • Thank you for your hints. The variants using "~" or "^%" instead of "%" only work if the new environment variable only contains a single path. As PYTHONPATH contains multiple, I solved it by reading in PYTHONPATH using os.environ[PYTHONPATH] (in python) and replacing all % characters by %" or "%. – golden96371 Jun 13 '19 at 16:10
  • 1
    If you're using Python, you should use the winreg module to read and modify the unexpanded value. For example: `k = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Environment');` `new_value = winreg.QueryValueEx(k, 'PYTHONPATH')[0] + r';%INSTALLATION_DIR%\Utility\Scripts'`. setx.exe notifies Explorer to update its environment, so you probably want to use it to set the value instead of winreg. For example: `subprocess.call('setx.exe PYTHONPATH "{}"'.format(new_value))`. Note there's no CMD shell involved in this case, so you don't have to worry about escaping percents in the command line. – Eryk Sun Jun 13 '19 at 20:09
  • Retrieving the unexpanded value can be done directly in bat/cmd as well, see [this answer](https://stackoverflow.com/a/45566845/2144408). – TamaMcGlinn Apr 01 '20 at 09:45
0

treat the % as you would treat a special character. double the % so

SETX PYTHONPATH "%PYTHONPATH%;%%INSTALLATION_DIR%%\Utility\Scripts"

user2648008
  • 152
  • 4
  • This results in %D:\Programs\MyProject%\Utility\Scripts – golden96371 Jun 13 '19 at 09:46
  • This answer should go into a bat file, and then be run. You pasted it directly into a CMD window, in which case you need to escape % with ^. Isn't CMD a wonderful programming language? – TamaMcGlinn Apr 01 '20 at 09:38