Bagaimana cara memperbarui variabel PATH secara permanen dari baris perintah Windows?

122

Jika saya mengeksekusi set PATH=%PATH%;C:\\Something\\bindari baris perintah ( cmd.exe) dan kemudian mengeksekusi echo %PATH%saya melihat string ini ditambahkan ke PATH. Jika saya menutup dan membuka baris perintah, string baru itu tidak ada di PATH.

Bagaimana cara memperbarui PATH secara permanen dari baris perintah untuk semua proses di masa mendatang, tidak hanya untuk proses saat ini?

Saya tidak ingin melakukan ini dengan membuka Properti Sistem → Lanjutan → Variabel lingkungan dan memperbarui PATH di sana.

Perintah ini harus dijalankan dari aplikasi Java (lihat pertanyaan saya yang lain ).

vale4674
sumber
5
Menggunakan PowerShell, stackoverflow.com/questions/714877/… cukup mudah . Menggunakan cmd, saya tidak yakin. Anda mungkin harus mengubah registri atau menarik rakitan .net entah bagaimana.
Austen Holmes
1
Seperti yang saya katakan, saya harus melakukan ini dari dalam aplikasi java. Saya pikir hanya untuk menjalankan beberapa perintah cmd useng javaRuntime.getRuntime().exec("my command");
vale4674

Jawaban:

43

Dokumentasi tentang cara melakukannya dapat ditemukan di MSDN . Ekstrak kuncinya adalah ini:

Untuk menambah atau mengubah variabel lingkungan sistem secara terprogram, tambahkan variabel tersebut ke kunci registri HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ Environment , lalu siarkan WM_SETTINGCHANGEpesan dengan lParam yang disetel ke string "Environment". Ini memungkinkan aplikasi, seperti shell, untuk mengambil pembaruan Anda.

Perhatikan bahwa aplikasi Anda memerlukan hak admin yang lebih tinggi agar dapat mengubah kunci ini.

Anda menunjukkan di komentar bahwa Anda dengan senang hati akan mengubah lingkungan per pengguna saja. Lakukan ini dengan mengedit nilai di HKEY_CURRENT_USER \ Environment . Seperti sebelumnya, pastikan Anda menyiarkan WM_SETTINGCHANGEpesan.

Anda seharusnya dapat melakukan ini dari aplikasi Java dengan cukup mudah menggunakan kelas registri JNI.

David Heffernan
sumber
1
Ya, menggunakan kelas registri JNI. Masalah yang lebih besar adalah aplikasi Anda mungkin tidak berjalan dengan baik. Tahukah Anda bagaimana membuatnya melakukan itu? Jika Anda hanya ingin sebagian kecil dari aplikasi Anda berjalan tinggi (yaitu hanya untuk melakukan perubahan ini) maka solusi paling sederhana adalah aplikasi C ++ yang sangat sederhana untuk melakukan pekerjaan, ditandai dengan manifes aplikasi, dan kemudian dijalankan sebagai proses terpisah yang memprovokasi dialog UAC.
David Heffernan
1
Anda juga dapat mengedit HKEY_CURRENT_USER\Environmentuntuk menghindari persyaratan ketinggian.
kichik
@David Heffernan Ya, hanya hal ini yang harus dijalankan lebih tinggi. Jadi saran Anda adalah menulis aplikasi C ++ dan menjalankannya dari aplikasi java saya? Dapatkah Anda memberi saya beberapa contoh kode atau tautan tentang cara melakukan ini?
vale4674
Ya. Seperti yang dikatakan David. Hanya Anda yang tidak meninggikan. Saya juga harus menyebutkan ini akan mengubah lingkungan hanya untuk pengguna saat ini.
kichik
Anda perlu memisahkan ini ke dalam proses terpisah sehingga Anda hanya memaksa dialog UAC saat memodifikasi PATH sistem. Ini hanya membutuhkan aplikasi C ++ sederhana dengan sedikit pembacaan dan penulisan registri, diikuti oleh SendMessage. Setel requestedExecutionLevelke requireAdministratordalam manifes aplikasi.
David Heffernan
145

Kamu bisa memakai:

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

Namun, setxakan memotong string yang disimpan menjadi 1024 byte, berpotensi merusak PATH.

/Makan mengubah PATHdalam, HKEY_LOCAL_MACHINEbukan HKEY_CURRENT_USER. Dengan kata lain, variabel sistem, bukan pengguna. Sebagai contoh:

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

Anda harus ingat, PATH baru tidak terlihat di Anda saat ini cmd.exe.

Tetapi jika Anda melihat di registri atau di baru cmd.exedengan "set p"Anda dapat melihat nilai baru.

panny
sumber
2
Apakah ada cara yang digunakan setxuntuk mengubah jalur mesin dan bukan jalur pengguna?
Corey Ogburn
4
Dari sini Anda dapat mengetahui bahwa dimungkinkan untuk menetapkan variabel tidak hanya untuk pengguna yang saat ini masuk tetapi untuk mesin dengan menggunakan /mdi akhir perintah, di windows xp dan 7. Saya belum mencobanya.
panny
1
Saya mendapat kesalahan saat menjalankan setxperintah "Opsi default tidak diperbolehkan lebih dari '2' waktu" Bagaimana cara memotongnya?
Nam G VU
12
Komentar @KilgoreCod: Saya berhati-hati untuk tidak menggunakan perintah: Pada banyak (kebanyakan?) Instalasi akhir-akhir ini, variabel PATH akan panjang - setx akan memotong string yang disimpan menjadi 1024 byte, berpotensi merusak PATH (lihat pembahasan di sini superuser.com/ q / 812754 ).
beresfordt
2
Saya mencoba menggemakan jalur itu sudah lebih dari 1200bytes. ada cara lain selain setx?
lawphotog
37

Saya berhati-hati agar tidak menggunakan perintah

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

untuk memodifikasi variabel PATH karena "fitur" implementasinya. Pada banyak (kebanyakan?) Penginstalan akhir-akhir ini, variabelnya akan menjadi panjang - setxakan memotong string yang disimpan menjadi 1024 byte, berpotensi merusak PATH (lihat pembahasan di sini ).

( Saya mendaftar secara khusus untuk menandai masalah ini, dan karena itu tidak memiliki reputasi situs untuk secara langsung mengomentari jawaban yang diposting pada 2 Mei '12. Terima kasih saya kepada beresfordt untuk menambahkan komentar seperti itu )

KilgoreCod
sumber
9

Skrip Python [*] ini melakukan persis seperti itu:

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

Di bawah ini adalah beberapa contoh penggunaan, dengan asumsi itu telah disimpan dalam file bernama setenv.pydi suatu tempat di jalur Anda saat ini. Perhatikan bahwa dalam contoh ini saya tidak memiliki hak admin , jadi perubahan hanya memengaruhi pohon registri pengguna lokal saya:

> 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

[*] Diadaptasi dari: http://code.activestate.com/recipes/416087-persistent-environment-variables-on-windows/

ankostis
sumber
4

Untuk tujuan referensi, bagi siapa pun yang mencari cara mengubah jalur melalui kode, saya mengutip posting berguna oleh programmer Delphi dari halaman web ini: http://www.tek-tips.com/viewthread.cfm?qid=686382

TonHu (Programmer) 22 Oct 03 17:57 Saya menemukan dimana saya membaca postingan aslinya, disini: http://news.jrsoftware.org/news/innosetup.isx/msg02129 ....

Kutipan dari apa yang Anda butuhkan adalah ini:

Anda harus menentukan string "Lingkungan" di LParam. Di Delphi Anda akan melakukannya dengan cara ini:

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

Ini disarankan oleh Jordan Russell, http://www.jrsoftware.org , penulis (ao) InnoSetup, ("Inno Setup adalah penginstal gratis untuk program Windows. Pertama kali diperkenalkan pada tahun 1997, Inno Setup saat ini menyaingi dan bahkan melampaui banyak pemasang komersial dalam kumpulan fitur dan stabilitas. ") (Saya hanya ingin lebih banyak orang menggunakan InnoSetup)

HTH

Steve F.
sumber
Anda harus mengubah registri. Juga, cast ke Integer buruk. Transmisikan ke LPARAM sebagai gantinya untuk kompatibilitas 64 bit.
David Heffernan
4

Di jaringan perusahaan, di mana pengguna hanya memiliki akses terbatas dan menggunakan aplikasi portabel, ada trik baris perintah berikut:

  1. Query variabel pengguna env: reg query "HKEY_CURRENT_USER\Environment". Gunakan "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"untuk LOCAL_MACHINE.
  2. Menambahkan variabel pengguna env baru: reg add "HKEY_CURRENT_USER\Environment" /v shared_dir /d "c:\shared" /t REG_SZ. Gunakan REG_EXPAND_SZuntuk jalur yang berisi variabel %% lainnya.
  3. Hapus variabel env yang ada: reg delete "HKEY_CURRENT_USER\Environment" /v shared_dir.
razvanone.dll
sumber
3

Skrip ini http://www.autohotkey.com/board/topic/63210-modify-system-path-gui/

menyertakan semua panggilan Windows API yang diperlukan yang dapat difaktorisasi ulang untuk kebutuhan Anda. Ini sebenarnya adalah GUI AutoHotkey untuk mengubah PATH Sistem dengan mudah. Perlu dijalankan sebagai Administrator.

Evgeni Sergeev
sumber
Baca pertanyaannya. Lagi.
jiggunjer
Naskah yang bagus. Saya menggunakan HotKey tetapi tidak tahu bagaimana atau apa yang perlu saya lakukan untuk menambahkan skrip ke dalamnya. Dapatkah Anda menawarkan bantuan, menawarkan tautan, atau menjelaskan apa yang perlu dilakukan?
jwzumwalt