簡體   English   中英

如何從 Windows 命令行永久更新 PATH 變量?

[英]How to update PATH variable permanently from Windows command line?

如果我從命令行( cmd.exe )執行set PATH=%PATH%;C:\\\\Something\\\\bin ,然后執行echo %PATH%我會看到這個字符串添加到 PATH 中。 如果我關閉並打開命令行,則該新字符串不在 PATH 中。

如何從命令行為將來的所有進程永久更新 PATH,而不僅僅是當前進程?

我不想通過轉到系統屬性 → 高級 → 環境變量並在那里更新 PATH 來做到這一點。

此命令必須從 Java 應用程序執行(請參閱我的其他問題)。

您可以使用:

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

但是, setx會將存儲的字符串截斷為 1024 字節,這可能會損壞 PATH。

/M將更改HKEY_LOCAL_MACHINEPATH而不是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:\Something\bin"

由於其實現的“功能”而修改 PATH 變量。 setx在許多(大多數?)安裝中,變量會很長 - 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'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的文件中。 請注意,在這些示例中,我沒有 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/

出於參考目的,對於任何搜索如何通過代碼更改路徑的人,我在此網頁上引用了 Delphi 程序員的一篇有用帖子: http : //www.tek-tips.com/viewthread.cfm?qid=686382

TonHu (Programmer) 22 Oct 03 17:57 我找到了我閱讀原始帖子的地方,它在這里: http : //news.jrsoftware.org/news/innosetup.isx/msg02129 ....

你需要的摘錄是這樣的:

您必須在 LParam 中指定字符串“Environment”。 在 Delphi 中,你會這樣做:

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

它是由 Jordan Russell 建議的, http: //www.jrsoftware.org,(ao) InnoSetup 的作者,(“Inno Setup 是 Windows 程序的免費安裝程序。1997 年首次推出,今天的 Inno Setup 與許多競爭對手相媲美,甚至超過了許多功能集和穩定性方面的商業安裝程序。”)(我只是希望更多人使用 InnoSetup )

HTH

在公司網絡中,用戶只有有限的訪問權限並使用便攜式應用程序,有以下命令行技巧:

  1. 查詢用戶reg query "HKEY_CURRENT_USER\\Environment"變量: reg query "HKEY_CURRENT_USER\\Environment" 對 LOCAL_MACHINE 使用"HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"
  2. 添加新的用戶reg add "HKEY_CURRENT_USER\\Environment" /v shared_dir /d "c:\\shared" /t REG_SZ變量: reg add "HKEY_CURRENT_USER\\Environment" /v shared_dir /d "c:\\shared" /t REG_SZ REG_EXPAND_SZ用於包含其他 %% 變量的路徑。
  3. 刪除現有reg delete "HKEY_CURRENT_USER\\Environment" /v shared_dir變量: reg delete "HKEY_CURRENT_USER\\Environment" /v shared_dir

這個腳本http://www.autohotkey.com/board/topic/63210-modify-system-path-gui/

包括所有必要的 Windows API 調用,可以根據您的需要進行重構。 它實際上是一個 AutoHotkey GUI,可以輕松更改系統路徑。 需要以管理員身份運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM