Làm cách nào để cập nhật biến PATH vĩnh viễn từ dòng lệnh Windows?


122

Nếu tôi thực thi set PATH=%PATH%;C:\\Something\\bintừ dòng lệnh ( cmd.exe) và sau đó thực thi, echo %PATH%tôi thấy chuỗi này được thêm vào PATH. Nếu tôi đóng và mở dòng lệnh, chuỗi mới đó không có trong PATH.

Làm cách nào để cập nhật PATH vĩnh viễn từ dòng lệnh cho tất cả các quy trình trong tương lai, không chỉ cho quy trình hiện tại?

Tôi không muốn làm điều này bằng cách đi tới Thuộc tính hệ thống → Nâng cao → Biến môi trường và cập nhật PATH ở đó.

Lệnh này phải được thực thi từ một ứng dụng Java (vui lòng xem câu hỏi khác của tôi ).


5
Sử dụng powershell, nó khá thẳng thắn stackoverflow.com/questions/714877/… . Sử dụng cmd, tôi không chắc chắn. Bạn có thể phải sửa đổi sổ đăng ký hoặc kéo vào một hội đồng .net bằng cách nào đó.
Austen Holmes

1
Như tôi đã nói, tôi phải làm điều này từ bên trong ứng dụng java. Tôi nghĩ chỉ để thực hiện một số lệnh cmd useng java củaRuntime.getRuntime().exec("my command");
vale4674

Câu trả lời:


43

Tài liệu về cách thực hiện việc này có thể tìm thấy trên MSDN . Nội dung chính là:

Để thêm hoặc sửa đổi các biến môi trường hệ thống theo chương trình, hãy thêm chúng vào khóa đăng ký HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ Environment , sau đó phát WM_SETTINGCHANGEthông báo với lParam được đặt thành chuỗi "Môi trường". Điều này cho phép các ứng dụng, chẳng hạn như shell, nhận các bản cập nhật của bạn.

Lưu ý rằng ứng dụng của bạn sẽ cần quyền quản trị nâng cao để có thể sửa đổi khóa này.

Bạn cho biết trong các nhận xét rằng bạn sẽ sẵn lòng chỉ sửa đổi môi trường cho mỗi người dùng. Thực hiện việc này bằng cách chỉnh sửa các giá trị trong HKEY_CURRENT_USER \ Environment . Như trước đây, hãy đảm bảo rằng bạn đã phát một WM_SETTINGCHANGEtin nhắn.

Bạn có thể thực hiện việc này từ ứng dụng Java của mình một cách dễ dàng bằng cách sử dụng các lớp đăng ký JNI.


1
Có, bằng cách sử dụng các lớp đăng ký JNI. Một vấn đề lớn hơn là ứng dụng của bạn có thể không chạy trên cao. Bạn có biết làm thế nào để làm cho nó làm điều đó? Nếu bạn chỉ muốn một phần nhỏ ứng dụng của mình chạy ở chế độ nâng cao (tức là chỉ để thực hiện thay đổi này) thì giải pháp đơn giản nhất là một ứng dụng C ++ rất đơn giản để thực hiện công việc, được đánh dấu bằng tệp kê khai ứng dụng, sau đó được thực thi như một quy trình riêng biệt. kích hoạt hộp thoại UAC.
David Heffernan

1
Bạn cũng có thể chỉnh sửa HKEY_CURRENT_USER\Environmentđể tránh yêu cầu về độ cao.
kichik

@David Heffernan Có chỉ điều này phải chạy trên cao. Vì vậy, đề xuất của bạn là viết ứng dụng C ++ và thực thi nó từ ứng dụng java của tôi? Bạn có thể cung cấp cho tôi một số mã ví dụ hoặc liên kết về cách thực hiện việc này không?
vale4674

Vâng. Đúng như David đã nói. Chỉ bạn không nâng cao. Tôi cũng nên đề cập đến điều này sẽ sửa đổi môi trường chỉ cho người dùng hiện tại.
kichik

Bạn cần tách điều này thành một quá trình riêng biệt để bạn chỉ buộc hộp thoại UAC khi sửa đổi PATH hệ thống. Nó chỉ cần một ứng dụng C ++ đơn giản với một vài đăng ký đọc và ghi, tiếp theo là một SendMessage. Đặt requestedExecutionLevelthành requireAdministratortrong tệp kê khai ứng dụng.
David Heffernan

145

Bạn có thể dùng:

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

Tuy nhiên, setxsẽ cắt ngắn chuỗi được lưu trữ thành 1024 byte, có khả năng làm hỏng PATH.

/Msẽ thay đổi PATHtrong HKEY_LOCAL_MACHINEthay vì HKEY_CURRENT_USER. Nói cách khác, một biến hệ thống, thay vì của người dùng. Ví dụ:

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

Bạn phải lưu ý, PATH mới không hiển thị trong hiện tại của bạn cmd.exe.

Nhưng nếu bạn nhìn vào registry hoặc trên một mới cmd.exevới "set p"bạn sẽ nhìn thấy giá trị mới.


2
Có cách nào sử dụng setxđể thay đổi đường dẫn của máy thay vì đường dẫn của người dùng không?
Corey Ogburn

4
Từ đây, bạn có thể biết có thể đặt một biến không chỉ cho người dùng đang đăng nhập mà còn cho máy bằng cách sử dụng /mở cuối lệnh, trên windows xp và 7. Tuy nhiên, tôi chưa thử.
panny

1
Tôi gặp lỗi khi chạy setxlệnh "Tùy chọn mặc định không được phép quá '2' thời gian" Làm thế nào để bỏ qua nó?
Nam G VU

12
@KilgoreCod nhận xét: Tôi thận trọng với việc sử dụng lệnh: Trên nhiều (hầu hết?) Cài đặt hiện nay, biến PATH sẽ dài - setx sẽ cắt ngắn chuỗi được lưu trữ thành 1024 byte, có khả năng làm hỏng PATH (xem thảo luận tại đây superuser.com/ q / 812754 ).
beresfordt

2
Tôi cố gắng lặp lại đường dẫn mà nó đã hơn 1200byte. bất kỳ cách nào khác thay vì setx?
lawphotog

37

Tôi thận trọng không sử dụng lệnh

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

để sửa đổi biến PATH vì một "tính năng" của việc triển khai nó. Trên nhiều (hầu hết?) Cài đặt ngày nay, biến sẽ dài - setxsẽ cắt ngắn chuỗi được lưu trữ thành 1024 byte, có khả năng làm hỏng PATH (xem thảo luận tại đây ).

( Tôi đã đăng ký đặc biệt để gắn cờ vấn đề này và do đó trang web thiếu uy tín để nhận xét trực tiếp về câu trả lời được đăng vào ngày 2 tháng 5 năm 12. Cảm ơn beresfordt đã thêm nhận xét như vậy )


9

Python-script [*] này thực hiện chính xác điều đó:

"""
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:])

Dưới đây là một số ví dụ sử dụng, giả sử nó đã được lưu trong một tệp có tên setenv.pyở đâu đó trong đường dẫn hiện tại của bạn. Lưu ý rằng trong các ví dụ này, tôi không có quyền quản trị , vì vậy các thay đổi chỉ ảnh hưởng đến cây đăng ký của người dùng cục bộ của tôi:

> 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

[*] Phỏng theo: http://code.activestate.com/recipes/416087-persists-enosystem-variables-on-windows/


4

Với mục đích tham khảo, cho bất kỳ ai đang tìm kiếm cách thay đổi đường dẫn qua mã, tôi trích dẫn một bài đăng hữu ích của một lập trình viên Delphi từ trang web này: http://www.tek-tips.com/viewthread.cfm?qid=686382

TonHu (Programmer) 22 03 Tháng Mười 17:57 Tôi tìm thấy nơi tôi đọc bài đăng ban đầu, nó ở đây: http://news.jrsoftware.org/news/innosetup.isx/msg02129 ....

Đoạn trích về những gì bạn cần là:

Bạn phải chỉ định chuỗi "Môi trường" trong LParam. Ở Delphi, bạn sẽ làm theo cách này:

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

Nó được gợi ý bởi Jordan Russell, http://www.jrsoftware.org , tác giả của (ao) InnoSetup, ("Inno Setup là trình cài đặt miễn phí cho các chương trình Windows. Được giới thiệu lần đầu vào năm 1997, Inno Setup ngày nay là đối thủ và thậm chí còn vượt qua nhiều trình cài đặt thương mại trong bộ tính năng và độ ổn định. ") (Tôi chỉ muốn nhiều người sử dụng InnoSetup hơn)

HTH


Bạn phải sửa đổi sổ đăng ký. Ngoài ra, diễn viên đến Số nguyên là kém. Truyền sang LPARAM để tương thích 64 bit.
David Heffernan


4

Trong mạng công ty, nơi người dùng chỉ có quyền truy cập hạn chế và sử dụng các ứng dụng di động, có những thủ thuật dòng lệnh sau:

  1. Truy vấn các biến sử dụng env: reg query "HKEY_CURRENT_USER\Environment". Sử dụng"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" cho LOCAL_MACHINE.
  2. Thêm biến người dùng env mới: reg add "HKEY_CURRENT_USER\Environment" /v shared_dir /d "c:\shared" /t REG_SZ. Sử dụngREG_EXPAND_SZ cho các đường dẫn có chứa các biến %% khác.
  3. Xóa biến env hiện có: reg delete "HKEY_CURRENT_USER\Environment" /v shared_dir.

3

Tập lệnh này http://www.autohotkey.com/board/topic/63210-modify-system-path-gui/

bao gồm tất cả các lệnh gọi API Windows cần thiết có thể được cấu trúc lại theo nhu cầu của bạn. Nó thực sự là một GUI AutoHotkey để thay đổi PATH hệ thống một cách dễ dàng. Cần được điều hành với tư cách là Quản trị viên.


Đọc câu hỏi. Lần nữa.
jiggunjer

Kịch bản tuyệt vời. Tôi sử dụng HotKey nhưng không biết cách hoặc những gì tôi cần làm để thêm tập lệnh vào đó. Bạn có thể giúp đỡ, cung cấp liên kết hoặc giải thích những gì cần phải làm không?
jwzumwalt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.