如何从Windows命令行永久更新PATH变量



如果我从命令行(cmd.exe(执行set PATH=%PATH%;C:\Something\bin,然后执行echo %PATH%,我会看到这个字符串被添加到PATH中。如果我关闭并打开命令行,则新字符串不在PATH中。

如何从命令行永久更新未来所有进程的PATH,而不仅仅是当前进程的PATH?

我不想通过转到"系统属性"来执行此操作→先进的→环境变量并在那里更新PATH。

这个命令必须在Java应用程序中执行(请参阅我的另一个问题(。

您可以使用:

setx PATH "%PATH%;C:\Something\bin"

但是,setx会将存储的字符串截断为1024个字节,这可能会损坏PATH。

/M将改变HKEY_LOCAL_MACHINE中的PATH而不是HKEY_CURRENT_USER。换句话说,系统变量,而不是用户的。例如:

SETX /M PATH "%PATH%;C:your path with spaces"

您必须记住,新的PATH在您当前的cmd.exe中不可见。

但是,如果您查看注册表或带有"set p"的新cmd.exe,您可以看到新值。

有关如何做到这一点的文档可以在MSDN上找到。关键摘录如下:

要以编程方式添加或修改系统环境变量,请将它们添加到HKEY_LOCAL_MACHINE\system\CurrentControlSet\Control\Session Manager\environment注册表项,然后广播一条WM_SETTINGCHANGE消息,其中lParam设置为字符串"environment"。这允许应用程序(如shell(获取您的更新。

请注意,您的应用程序需要提升管理权限才能修改此密钥。

您在评论中指出,您很乐意只修改每个用户的环境。通过编辑HKEY_CURRENT_USER\Environment中的值来执行此操作。和以前一样,请确保广播WM_SETTINGCHANGE消息。

您应该能够使用JNI注册表类从Java应用程序轻松地完成这项工作。

我警告不要使用命令

setx PATH "%PATH%;C:Somethingbin"

修改PATH变量,因为它的实现具有"特性"。如今,在许多(大多数?(安装中,变量会很长——setx会将存储的字符串截断为1024字节,可能会损坏PATH(请参阅此处的讨论(。

(我专门注册来标记这个问题,因此缺乏直接评论12年5月2日发布的答案的网站声誉。我感谢beresfordt添加这样的评论(

这个Python脚本[*]正是这样做的:

"""
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'SYSTEMCurrentControlSetControlSession ManagerEnvironment'),
        ('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:])

以下是一些使用示例,假设它已保存在当前路径中某个名为setenv.py的文件中。请注意,在这些示例中,我没有管理员权限,因此这些更改只影响我的本地用户的注册表树:

> REM ## Print all env-vars
> setenv.py
!!!Cannot access HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession   ManagerEnvironment:PATH due to: [WinError 5] Access is denied
HKEY_CURRENT_USEREnvironment:PATH=...
...
> REM ## Query env-var:
> setenv.py PATH C:foo
!!!Cannot access HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession   ManagerEnvironment:PATH due to: [WinError 5] Access is denied
!!!Cannot find HKEY_CURRENT_USEREnvironment: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_MACHINESYSTEMCurrentControlSetControlSession   ManagerEnvironment:PATH due to: [WinError 5] Access is denied
---Set HKEY_CURRENT_USEREnvironment:PATH=C:foo
> REM ## Append env-var:
> setenv.py +PATH D:Bar
!!!Cannot access HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession   ManagerEnvironment:PATH due to: [WinError 5] Access is denied
---Set HKEY_CURRENT_USEREnvironment:PATH=C:foo;D:Bar
> REM ## Delete env-var:
> setenv.py -PATH
!!!Cannot access HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession   ManagerEnvironment:PATH due to: [WinError 5] Access is denied
---Deleted HKEY_CURRENT_USEREnvironment:PATH

[*]改编自:http://code.activestate.com/recipes/416087-persistent-environment-variables-on-windows/

为了参考,对于任何搜索如何通过代码更改路径的人,我引用了Delphi程序员在这个网页上的一篇有用的帖子:http://www.tek-tips.com/viewthread.cfm?qid=686382

TonHu(程序员(03年10月22日17:57我发现了我阅读原文的地方张贴,它在这里:http://news.jrsoftware.org/news/innosetup.isx/msg02129....

你需要的摘录是:

您必须在LParam中指定字符串"Environment"。在德尔福,你会这样做:

 SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, Integer(PChar('Environment')));

这是Jordan Russell提出的,http://www.jrsoftware.org这个(a.o.(InnoSetup的作者,("InnoSetum是Windows程序。Inno Setup于1997年首次推出,如今已成为竞争对手甚至在功能集和稳定性"((我只是希望更多的人使用InnoSetup(

HTH-

在公司网络中,用户只能有限地访问并使用便携式应用程序,有以下命令行技巧:

  1. 查询用户环境变量:reg query "HKEY_CURRENT_USEREnvironment"。将"HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerEnvironment"用于LOCAL_MACHINE
  2. 添加新的用户环境变量:reg add "HKEY_CURRENT_USEREnvironment" /v shared_dir /d "c:shared" /t REG_SZ。对于包含其他%%变量的路径,请使用REG_EXPAND_SZ
  3. 删除现有的env变量:reg delete "HKEY_CURRENT_USEREnvironment" /v shared_dir

此脚本http://www.autohotkey.com/board/topic/63210-modify-system-path-gui/

包括所有必要的Windows API调用,这些调用可以根据您的需要进行重构。它实际上是一个自动热键GUI,可以很容易地更改系统路径。需要以管理员身份运行。

最新更新