How to update PATH variable permanently from Windows command line?
Asked Answered
B

7

129

If I execute set PATH=%PATH%;C:\\Something\\bin from the command line (cmd.exe) and then execute echo %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).

Bunk answered 2/12, 2011 at 15:3 Comment(4)
Using powershell, it's fairly straightfoward stackoverflow.com/questions/714877/…. Using cmd, I'm not sure. You may have to modify the registry or pull in a .net assembly somehow.Collect
As I said, I have to do this from within java application. I thought just to execute some cmd command useng java's Runtime.getRuntime().exec("my command");Bunk
Does this answer your question? Adding a directory to the PATH environment variable in WindowsJanel
This does not become a Java question simply because OP wanted to execute the command from within a Java application. It's purely OS-level functionality; and "how do I execute a DOS command from Java?" is a separate and orthogonal question (i.e., running the command from Java doesn't depend on what the command is, and figuring out the command doesn't depend on the fact that it will be executed programmatically, nor on what language would be used).Sands
G
43

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.

Gentleman answered 2/12, 2011 at 15:9 Comment(13)
Yes, 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.Gentleman
You can also edit HKEY_CURRENT_USER\Environment to avoid elevation requirement.Thereon
@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?Bunk
Yep. Just like David said. Only you don't elevation. I should also mention this will modify the environment for the current user only.Thereon
You 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 to requireAdministrator in the app manifest.Gentleman
@Thereon 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 with Runtime.getRuntime().exec("my command"); It is acceptable that this will modify PATH only for the current user.Bunk
@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.Bunk
If I were you, I'd just handle all this in the installer of your application. Every decent installation framework can change the environment.Thereon
If 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.Gentleman
@Thereon 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.Bunk
Oh, and @Thereon 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.Gentleman
There 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.Thereon
I 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.Bunk
G
144

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.

Goldenrod answered 2/5, 2012 at 9:33 Comment(14)
Is there a way to use setx to change the machine's path instead of the user's path?Galleywest
From 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.Goldenrod
I got the error when running setx command "Default option is not allowed more than '2' time" How to bypass it?Tambac
I missed the quote for the value of PATHTambac
setx doesn't store the PATH value to the actual system variable!Tambac
Interestingly, I had the correct path in my registry but cmd didn't get it until I ran setx. Thanks +1, but why??!!Defamatory
setx cmd doesn't store the PATH value to the system variables. It makes changes to user variables instead.Tambac
It does if you use /M just as panny mentioned it above. For an instance: setx PATH "%PATH%;C:\Somepath" /MInsinuating
As other said, this does not update your system PATH but duplicates entries from system PATH into user's PATH...Skurnik
A possible drawback might be that all variables within PATH will get resolved.Barbuto
@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).Primrose
@Primrose - Wish I'd seen that comment first. I've edited the warning into the answer.Martyrize
When I run setx PATH "%PATH%;C:\\Program Files\\R\\R-3.3.2\\bin", I get ERROR: Invalid syntax. Default option is not allowed more than '2' time(s).Erminiaerminie
I try to echo out the path it's already over 1200bytes. any other way instead of setx?Streetlight
G
43

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.

Gentleman answered 2/12, 2011 at 15:9 Comment(13)
Yes, 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.Gentleman
You can also edit HKEY_CURRENT_USER\Environment to avoid elevation requirement.Thereon
@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?Bunk
Yep. Just like David said. Only you don't elevation. I should also mention this will modify the environment for the current user only.Thereon
You 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 to requireAdministrator in the app manifest.Gentleman
@Thereon 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 with Runtime.getRuntime().exec("my command"); It is acceptable that this will modify PATH only for the current user.Bunk
@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.Bunk
If I were you, I'd just handle all this in the installer of your application. Every decent installation framework can change the environment.Thereon
If 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.Gentleman
@Thereon 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.Bunk
Oh, and @Thereon 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.Gentleman
There 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.Thereon
I 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.Bunk
H
39

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)

Hallowell answered 16/6, 2015 at 19:16 Comment(0)
D
9

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/

Declivous answered 6/2, 2015 at 11:56 Comment(0)
A
4

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

Arlaarlan answered 23/3, 2013 at 22:36 Comment(2)
You have to modify the registry. Also, the cast to Integer is poor. Cast to LPARAM instead for 64 bit compatibility.Gentleman
Here is example github.com/gilligan/snesdev/blob/1253994/tools/cc65-2.13.2/…Albric
P
4

In a corporate network, where the user has only limited access and uses portable apps, there are these command line tricks:

  1. Query the user env variables: reg query "HKEY_CURRENT_USER\Environment". Use "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" for LOCAL_MACHINE.
  2. Add new user env variable: reg add "HKEY_CURRENT_USER\Environment" /v shared_dir /d "c:\shared" /t REG_SZ. Use REG_EXPAND_SZ for paths containing other %% variables.
  3. Delete existing env variable: reg delete "HKEY_CURRENT_USER\Environment" /v shared_dir.
Porter answered 9/5, 2017 at 15:26 Comment(0)
T
3

This script http://www.autohotkey.com/board/topic/63210-modify-system-path-gui/

includes all the necessary Windows API calls which can be refactored for your needs. It is actually an AutoHotkey GUI to change the System PATH easily. Needs to be run as an Administrator.

Tirza answered 15/8, 2013 at 10:47 Comment(1)
Great 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?Carolus

© 2022 - 2024 — McMap. All rights reserved.