How to update PATH variable permanently from Windows command line?
Solution 1
The documentation on how to do this can be found on MSDN. The key extract is this:
To programmatically add or modify system environment variables, add them to the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment registry key, then broadcast a
WM_SETTINGCHANGE
message with lParam set to the string "Environment". This allows applications, such as the shell, to pick up your updates.
Note that your application will need elevated admin rights in order to be able to modify this key.
You indicate in the comments that you would be happy to modify just the per-user environment. Do this by editing the values in HKEY_CURRENT_USER\Environment. As before, make sure that you broadcast a WM_SETTINGCHANGE
message.
You should be able to do this from your Java application easily enough using the JNI registry classes.
Solution 2
You can use:
setx PATH "%PATH%;C:\\Something\\bin"
However, setx
will truncate the stored string to 1024 bytes, potentially corrupting the PATH.
/M
will change the PATH
in HKEY_LOCAL_MACHINE
instead of HKEY_CURRENT_USER
. In other words, a system variable, instead of the user's. For example:
SETX /M PATH "%PATH%;C:\your path with spaces"
You have to keep in mind, the new PATH is not visible in your current cmd.exe
.
But if you look in the registry or on a new cmd.exe
with "set p"
you can see the new value.
Solution 3
I caution against using the command
setx PATH "%PATH%;C:\Something\bin"
to modify the PATH variable because of a "feature" of its implementation. On many (most?) installations these days the variable will be lengthy - setx
will truncate the stored string to 1024 bytes, potentially corrupting the PATH (see the discussion here).
(I signed up specifically to flag this issue, and so lack the site reputation to directly comment on the answer posted on May 2 '12. My thanks to beresfordt for adding such a comment)
Solution 4
This Python-script[*] does exactly that:
"""
Show/Modify/Append registry env-vars (ie `PATH`) and notify Windows-applications to pickup changes.
First attempts to show/modify HKEY_LOCAL_MACHINE (all users), and
if not accessible due to admin-rights missing, fails-back
to HKEY_CURRENT_USER.
Write and Delete operations do not proceed to user-tree if all-users succeed.
Syntax:
{prog} : Print all env-vars.
{prog} VARNAME : Print value for VARNAME.
{prog} VARNAME VALUE : Set VALUE for VARNAME.
{prog} +VARNAME VALUE : Append VALUE in VARNAME delimeted with ';' (i.e. used for `PATH`).
{prog} -VARNAME : Delete env-var value.
Note that the current command-window will not be affected,
changes would apply only for new command-windows.
"""
import winreg
import os, sys, win32gui, win32con
def reg_key(tree, path, varname):
return '%s\%s:%s' % (tree, path, varname)
def reg_entry(tree, path, varname, value):
return '%s=%s' % (reg_key(tree, path, varname), value)
def query_value(key, varname):
value, type_id = winreg.QueryValueEx(key, varname)
return value
def yield_all_entries(tree, path, key):
i = 0
while True:
try:
n,v,t = winreg.EnumValue(key, i)
yield reg_entry(tree, path, n, v)
i += 1
except OSError:
break ## Expected, this is how iteration ends.
def notify_windows(action, tree, path, varname, value):
win32gui.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')
print("---%s %s" % (action, reg_entry(tree, path, varname, value)), file=sys.stderr)
def manage_registry_env_vars(varname=None, value=None):
reg_keys = [
('HKEY_LOCAL_MACHINE', r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'),
('HKEY_CURRENT_USER', r'Environment'),
]
for (tree_name, path) in reg_keys:
tree = eval('winreg.%s'%tree_name)
try:
with winreg.ConnectRegistry(None, tree) as reg:
with winreg.OpenKey(reg, path, 0, winreg.KEY_ALL_ACCESS) as key:
if not varname:
for regent in yield_all_entries(tree_name, path, key):
print(regent)
else:
if not value:
if varname.startswith('-'):
varname = varname[1:]
value = query_value(key, varname)
winreg.DeleteValue(key, varname)
notify_windows("Deleted", tree_name, path, varname, value)
break ## Don't propagate into user-tree.
else:
value = query_value(key, varname)
print(reg_entry(tree_name, path, varname, value))
else:
if varname.startswith('+'):
varname = varname[1:]
value = query_value(key, varname) + ';' + value
winreg.SetValueEx(key, varname, 0, winreg.REG_EXPAND_SZ, value)
notify_windows("Updated", tree_name, path, varname, value)
break ## Don't propagate into user-tree.
except PermissionError as ex:
print("!!!Cannot access %s due to: %s" %
(reg_key(tree_name, path, varname), ex), file=sys.stderr)
except FileNotFoundError as ex:
print("!!!Cannot find %s due to: %s" %
(reg_key(tree_name, path, varname), ex), file=sys.stderr)
if __name__=='__main__':
args = sys.argv
argc = len(args)
if argc > 3:
print(__doc__.format(prog=args[0]), file=sys.stderr)
sys.exit()
manage_registry_env_vars(*args[1:])
Below are some usage examples, assuming it has been saved in a file called setenv.py
somewhere in your current path.
Note that in these examples i didn't have admin-rights, so the changes affected only my local user's registry tree:
> REM ## Print all env-vars
> setenv.py
!!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment:PATH due to: [WinError 5] Access is denied
HKEY_CURRENT_USER\Environment:PATH=...
...
> REM ## Query env-var:
> setenv.py PATH C:\foo
!!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment:PATH due to: [WinError 5] Access is denied
!!!Cannot find HKEY_CURRENT_USER\Environment:PATH due to: [WinError 2] The system cannot find the file specified
> REM ## Set env-var:
> setenv.py PATH C:\foo
!!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment:PATH due to: [WinError 5] Access is denied
---Set HKEY_CURRENT_USER\Environment:PATH=C:\foo
> REM ## Append env-var:
> setenv.py +PATH D:\Bar
!!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment:PATH due to: [WinError 5] Access is denied
---Set HKEY_CURRENT_USER\Environment:PATH=C:\foo;D:\Bar
> REM ## Delete env-var:
> setenv.py -PATH
!!!Cannot access HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment:PATH due to: [WinError 5] Access is denied
---Deleted HKEY_CURRENT_USER\Environment:PATH
[*] Adapted from: http://code.activestate.com/recipes/416087-persistent-environment-variables-on-windows/
Solution 5
For reference purpose, for anyone searching how to change the path via code, I am quoting a useful post by a Delphi programmer from this web page: http://www.tek-tips.com/viewthread.cfm?qid=686382
TonHu (Programmer) 22 Oct 03 17:57 I found where I read the original posting, it's here: http://news.jrsoftware.org/news/innosetup.isx/msg02129....
The excerpt of what you would need is this:
You must specify the string "Environment" in LParam. In Delphi you'd do it this way:
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, Integer(PChar('Environment')));
It was suggested by Jordan Russell, http://www.jrsoftware.org, the author of (a.o.) InnoSetup, ("Inno Setup is a free installer for Windows programs. First introduced in 1997, Inno Setup today rivals and even surpasses many commercial installers in feature set and stability.") (I just would like more people to use InnoSetup )
HTH
vale4674
Updated on October 30, 2020Comments
-
vale4674 over 3 years
If I execute
set PATH=%PATH%;C:\\Something\\bin
from the command line (cmd.exe
) and then executeecho %PATH%
I see this string added to the PATH. If I close and open the command line, that new string is not in PATH.How can I update PATH permanently from the command line for all processes in the future, not just for the current process?
I don't want to do this by going to System Properties → Advanced → Environment variables and update PATH there.
This command must be executed from a Java application (please see my other question).
-
David Heffernan over 12 yearsYes, using the JNI registry classes. A bigger issue is that your app probably doesn't run elevated. Do you know how to make it do that? If you only want a small portion of your app to run elevated (i.e. just to do this change) then the simplest solution is a very simple C++ app to do the job, marked with the app manifest, and then executed as a separate process which provokes the UAC dialog.
-
kichik over 12 yearsYou can also edit
HKEY_CURRENT_USER\Environment
to avoid elevation requirement. -
vale4674 over 12 years@David Heffernan Yes only this thing has to run elevated. So your suggestion is to write C++ application and execute it from my java application? Can you provide me some example code or link on how to do this?
-
kichik over 12 yearsYep. Just like David said. Only you don't elevation. I should also mention this will modify the environment for the current user only.
-
David Heffernan over 12 yearsYou need to separate this into a separate process so that you only force a UAC dialog when modifying system PATH. It just needs a simple C++ app with a few registry reads and writes, followed by a SendMessage. Set the
requestedExecutionLevel
torequireAdministrator
in the app manifest. -
vale4674 over 12 years@kichik Can you please provide me example command for updating this? I just wan't to add
C:\Program Files\Program
to the PATH. Can this update be run from CMD? If so then I can run the command withRuntime.getRuntime().exec("my command");
It is acceptable that this will modify PATH only for the current user. -
vale4674 over 12 years@David Heffernan I am confused now, do I need that C++ program or not? kichink confused me when he said that it can be done from java app. I am not sure if he is thinking also that I need C++ program.
-
kichik over 12 yearsIf I were you, I'd just handle all this in the installer of your application. Every decent installation framework can change the environment.
-
David Heffernan over 12 yearsIf you need to elevate then you need a separate process. Otherwise you are forced to running your entire app elevated which is bad practice and your users will hate you! If you just wish to change the per-user environment variable then you can modify the registry settings in HKCU\Environment.
-
vale4674 over 12 years@kichik That sure is the best way for the job but my application does not have an installation, it's just a runnable .jar and it is simpler for user just to run it from everywhere rather than have an installation. Also, my app designed for all platforms.
-
David Heffernan over 12 yearsOh, and @kichik is right, if this is a one time operation then do it as part of installation which is the one time it is reasonable to assume that you have admin rights.
-
kichik over 12 yearsThere is no cross platform way you can permanently change the environment. Make your life and the user's life easier by creating an installer or at least a wrapper for Windows.
-
vale4674 over 12 yearsI know that there isn't cross platform environment change, that thing would me done only if the app is run on Windows. I already took a look at IzPack installer but it looks complicated to modify it. I'll take a look at Launch4j.
-
Corey Ogburn over 11 yearsIs there a way to use
setx
to change the machine's path instead of the user's path? -
panny over 11 yearsFrom here you can tell it might be possible to set a variable not only for the currently logged in user but for the machine by using
/m
at the end of the command, on windows xp and 7. I haven't tried it though. -
Nam G VU over 10 yearsI got the error when running
setx
command "Default option is not allowed more than '2' time" How to bypass it? -
Nam G VU over 10 yearsI missed the quote for the value of PATH
-
Nam G VU over 10 yearssetx doesn't store the PATH value to the actual system variable!
-
Lzh over 10 yearsInterestingly, I had the correct path in my registry but cmd didn't get it until I ran setx. Thanks +1, but why??!!
-
Nam G VU almost 10 years
setx
cmd doesn't store the PATH value to the system variables. It makes changes to user variables instead. -
Danny Lo over 9 yearsIt does if you use
/M
just as panny mentioned it above. For an instance:setx PATH "%PATH%;C:\Somepath" /M
-
cubuspl42 over 9 yearsAs other said, this does not update your system PATH but duplicates entries from system PATH into user's PATH...
-
Qwerty over 9 yearsA possible drawback might be that all variables within
PATH
will get resolved. -
David Heffernan about 9 yearsYou have to modify the registry. Also, the cast to Integer is poor. Cast to LPARAM instead for 64 bit compatibility.
-
beresfordt almost 9 years@KilgoreCod comments: I caution against using the command: On many (most?) installations these days the PATH variable will be lengthy - setx will truncate the stored string to 1024 bytes, potentially corrupting the PATH (see the discussion here superuser.com/q/812754).
-
Martin Smith over 8 years@beresfordt - Wish I'd seen that comment first. I've edited the warning into the answer.
-
Admin almost 8 yearsHere is example github.com/gilligan/snesdev/blob/1253994/tools/cc65-2.13.2/…
-
wlad over 7 yearsWhen I run
setx PATH "%PATH%;C:\\Program Files\\R\\R-3.3.2\\bin"
, I getERROR: Invalid syntax. Default option is not allowed more than '2' time(s)
. -
Laurence about 6 yearsI try to echo out the path it's already over 1200bytes. any other way instead of setx?
-
jwzumwalt over 5 yearsGreat script. I use HotKey but don't know how or what I need to do to add the script to it. Can you offer help, offer a link, or explain what needs to be done?