首页 文章

如何从cmd永久更新PATH变量?视窗

提问于
浏览
114

如果我从cmd执行 set PATH=%PATH%;C:\\Something\\bin 然后执行 echo %PATH% 我看到在路径中添加了这个字符串 . 如果我关闭并打开cmd,则该新字符串不在PATH中 . 如何在将来从cmd为所有进程永久更新PATH,而不仅仅是针对当前进程?我不需要通过转到系统属性 - >高级 - >环境变量来执行此操作,然后更新PATH .

必须从java应用程序(我的其他question)执行此命令 .

7 回答

  • 34

    有关如何执行此操作的文档可在MSDN上找到 . 关键提取是这样的:

    要以编程方式添加或修改系统环境变量,请将它们添加到HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ Environment注册表项,然后广播WM_SETTINGCHANGE消息,并将lParam设置为字符串“Environment” . 这允许应用程序(如shell)获取更新 .

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

    您在评论中表明您很乐意仅修改每用户环境 . 通过编辑 HKEY_CURRENT_USER\Environment 中的值来完成此操作 . 和以前一样,请确保广播WM_SETTINGCHANGE消息 .

    您应该能够使用JNI注册表类轻松地从Java应用程序执行此操作 .

  • 2

    您可以使用:

    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 ,您可以看到新值 .

  • 2

    我提醒不要使用该命令

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

    修改PATH变量,因为它的实现是"feature" . 如今,在许多(大多数?)安装中,变量将很长 - setx 会将存储的字符串截断为1024字节,从而可能破坏PATH(请参阅讨论here) .

    (我专门报名参加了这个问题,所以缺乏网站声誉直接评论12月5日发布的答案 . 感谢beresfordt添加这样的评论)

  • 143

    这个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'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:])
    

    下面是一些使用示例,假设它已保存在当前路径中某个名为 setenv.py 的文件中 . 请注意,在这些示例i didn't have admin-rights 中,所以更改仅影响我本地用户的注册表树:

    > 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
    

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

  • 3

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

    TonHu(程序员)08年10月22日17:57我发现我在哪里阅读原始帖子,它就在这里:http://news.jrsoftware.org/news/innosetup.isx/msg02129 ....你想要的摘录需要是这样的:您必须在LParam中指定字符串“Environment” . 在Delphi中你可以这样做:SendMessage(HWND_BROADCAST,WM_SETTINGCHANGE,0,Integer(PChar('Environment')));
    这是(ao)InnoSetup的作者,约翰罗素,http://www.jrsoftware.org的建议,(“Inno Setup是一个免费的Windows程序安装程序 . 1997年首次推出,Inno Setup今天竞争甚至超过许多功能设置和稳定性的商业安装人员 . “)(我只是希望更多人使用InnoSetup)HTH

  • 41

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

    包括所有必要的Windows API调用,可以根据您的需要进行重构 . 它实际上是一个AutoHotkey GUI,可以轻松更改系统路径 . 需要以管理员身份运行 .

  • 7

    在企业网络中,用户只能访问有限且使用便携式应用程序,这些命令行技巧有:

    • 查询用户env变量: reg query "HKEY_CURRENT_USER\Environment" . 将 "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" 用于LOCAL_MACHINE .

    • 添加新用户env变量: reg add "HKEY_CURRENT_USER\Environment" /v shared_dir /d "c:\shared" /t REG_SZ . 对于包含其他%%变量的路径,请使用 REG_EXPAND_SZ .

    • 删除现有的env变量: reg delete "HKEY_CURRENT_USER\Environment" /v shared_dir .

相关问题