Come aggiornare la variabile PATH in modo permanente dalla riga di comando di Windows?


122

Se eseguo set PATH=%PATH%;C:\\Something\\bindalla riga di comando ( cmd.exe) e poi eseguo echo %PATH%vedo questa stringa aggiunta al PATH. Se chiudo e apro la riga di comando, quella nuova stringa non è in PATH.

Come posso aggiornare in modo permanente PATH dalla riga di comando per tutti i processi in futuro, non solo per il processo corrente?

Non voglio farlo andando su Proprietà di sistema → Avanzate → Variabili d'ambiente e aggiorna PATH lì.

Questo comando deve essere eseguito da un'applicazione Java (vedere la mia altra domanda ).


5
Utilizzando PowerShell, è abbastanza semplice stackoverflow.com/questions/714877/… . Utilizzando cmd, non sono sicuro. Potrebbe essere necessario modificare il registro o inserire un assembly .net in qualche modo.
Austen Holmes

1
Come ho detto, devo farlo dall'interno dell'applicazione java. Ho pensato solo di eseguire alcuni comandi cmd useng java'sRuntime.getRuntime().exec("my command");
vale4674

Risposte:


43

La documentazione su come eseguire questa operazione può essere trovata su MSDN . L'estratto chiave è questo:

Per aggiungere o modificare a livello di codice variabili di ambiente di sistema, aggiungerle alla chiave di registro HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ Environment , quindi trasmettere un WM_SETTINGCHANGEmessaggio con lParam impostato sulla stringa "Environment". Ciò consente alle applicazioni, come la shell, di raccogliere i tuoi aggiornamenti.

Tieni presente che la tua applicazione richiederà diritti di amministratore elevati per poter modificare questa chiave.

Indichi nei commenti che saresti felice di modificare solo l'ambiente per utente. A tale scopo, modificare i valori in HKEY_CURRENT_USER \ Environment . Come prima, assicurati di trasmettere un WM_SETTINGCHANGEmessaggio.

Dovresti essere in grado di farlo dalla tua applicazione Java abbastanza facilmente usando le classi di registro JNI.


1
Sì, utilizzando le classi di registro JNI. Un problema più grande è che la tua app probabilmente non viene eseguita con privilegi elevati. Sai come farlo fare? Se desideri che solo una piccola parte della tua app venga eseguita con privilegi elevati (ovvero solo per eseguire questa modifica), la soluzione più semplice è un'app C ++ molto semplice per eseguire il lavoro, contrassegnata con il manifesto dell'app e quindi eseguita come processo separato che provoca la finestra di dialogo UAC.
David Heffernan

1
È inoltre possibile modificare HKEY_CURRENT_USER\Environmentper evitare requisiti di elevazione.
kichik

@David Heffernan Sì, solo questa cosa deve essere elevata. Quindi il tuo suggerimento è di scrivere un'applicazione C ++ ed eseguirla dalla mia applicazione java? Potete fornirmi un codice di esempio o un collegamento su come farlo?
vale4674

Sì. Proprio come ha detto David. Solo tu non elevi. Dovrei anche menzionare che questo modificherà l'ambiente solo per l'utente corrente.
kichik

È necessario separarlo in un processo separato in modo da forzare una finestra di dialogo UAC solo quando si modifica il PERCORSO del sistema. Ha solo bisogno di una semplice app C ++ con alcune letture e scritture del registro, seguite da un SendMessage. Imposta il requestedExecutionLevelsu requireAdministratornel manifesto dell'app.
David Heffernan

145

Puoi usare:

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

Tuttavia, setxtroncerà la stringa memorizzata a 1024 byte, danneggiando potenzialmente il PERCORSO.

/Mcambierà PATHin HKEY_LOCAL_MACHINEinvece di HKEY_CURRENT_USER. In altre parole, una variabile di sistema, invece dell'utente. Per esempio:

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

Devi tenere a mente, il nuovo PERCORSO non è visibile nel tuo attuale cmd.exe.

Ma se guardi nel registro o su un nuovo cmd.execon "set p"puoi vedere il nuovo valore.


2
C'è un modo per setxmodificare il percorso della macchina invece del percorso dell'utente?
Corey Ogburn

4
Da qui puoi dire che potrebbe essere possibile impostare una variabile non solo per l'utente attualmente connesso ma per la macchina utilizzando /malla fine del comando, su Windows XP e 7. Non l'ho provato però.
panny

1
Ho ricevuto l'errore durante l'esecuzione del setxcomando "L'opzione predefinita non è consentita per più di '2' volte" Come bypassarla?
Nam G VU

12
@KilgoreCod commenta: Metto in guardia dall'usare il comando: su molte (la maggior parte?) Installazioni di questi tempi la variabile PATH sarà lunga - setx troncherà la stringa memorizzata a 1024 byte, corrompendo potenzialmente il PERCORSO (vedi la discussione qui superuser.com/ q / 812754 ).
beresfordt

2
Provo a ripetere il percorso che è già superiore a 1200 byte. qualsiasi altro modo invece di setx?
lawphotog

37

Metto in guardia contro l'utilizzo del comando

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

modificare la variabile PATH a causa di una "caratteristica" della sua implementazione. In molte (la maggior parte?) Installazioni di questi tempi la variabile sarà lunga: setxtroncerà la stringa memorizzata a 1024 byte, corrompendo potenzialmente il PERCORSO (vedere la discussione qui ).

( Mi sono registrato specificamente per segnalare questo problema, e quindi mi manca la reputazione del sito per commentare direttamente la risposta pubblicata il 2 maggio '12. Ringrazio beresfordt per aver aggiunto un commento del genere )


9

Questo script Python [*] fa esattamente questo:

"""
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 seguito sono riportati alcuni esempi di utilizzo, supponendo che sia stato salvato in un file chiamato setenv.pyda qualche parte nel percorso corrente. Nota che in questi esempi non avevo i diritti di amministratore , quindi le modifiche hanno interessato solo l'albero del registro dell'utente locale:

> 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

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


4

A scopo di riferimento, per chiunque cerchi come modificare il percorso tramite codice, sto citando un utile post di un programmatore Delphi da questa pagina web: http://www.tek-tips.com/viewthread.cfm?qid=686382

TonHu (Programmatore) 22 ottobre 03 17:57 Ho trovato dove ho letto il messaggio originale, è qui: http://news.jrsoftware.org/news/innosetup.isx/msg02129 ....

L'estratto di ciò di cui avresti bisogno è questo:

È necessario specificare la stringa "Ambiente" in LParam. In Delphi lo faresti in questo modo:

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

È stato suggerito da Jordan Russell, http://www.jrsoftware.org , l'autore di (ao) InnoSetup, ("Inno Setup è un programma di installazione gratuito per i programmi Windows. Introdotto per la prima volta nel 1997, Inno Setup oggi rivaleggia e supera anche molti installatori commerciali in set di funzionalità e stabilità. ") (Vorrei solo che più persone utilizzassero InnoSetup)

HTH


Devi modificare il registro. Inoltre, il cast di Integer è scadente. Trasmetti invece a LPARAM per la compatibilità a 64 bit.
David Heffernan


4

In una rete aziendale, in cui l'utente ha solo un accesso limitato e utilizza app portatili, esistono questi trucchi da riga di comando:

  1. Interrogare le variabili utente env: reg query "HKEY_CURRENT_USER\Environment". Utilizzare "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"per LOCAL_MACHINE.
  2. Aggiungi nuova variabile utente ENV: reg add "HKEY_CURRENT_USER\Environment" /v shared_dir /d "c:\shared" /t REG_SZ. Utilizzare REG_EXPAND_SZper percorsi contenenti altre variabili %%.
  3. Cancellare variabile ENV esistente: reg delete "HKEY_CURRENT_USER\Environment" /v shared_dir.

3

Questo script http://www.autohotkey.com/board/topic/63210-modify-system-path-gui/

include tutte le chiamate API Windows necessarie che possono essere modificate per le tue esigenze. In realtà è una GUI di AutoHotkey per modificare facilmente il PERCORSO del sistema. Deve essere eseguito come amministratore.


Leggi la domanda. Ancora.
jiggunjer

Ottimo copione. Uso HotKey ma non so come o cosa devo fare per aggiungere lo script. Potete offrire aiuto, offrire un collegamento o spiegare cosa è necessario fare?
jwzumwalt
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.