Як постійно оновлювати змінну PATH з командного рядка Windows?


122

Якщо я виконую set PATH=%PATH%;C:\\Something\\binз командного рядка ( cmd.exe), а потім виконую, echo %PATH%я бачу, що ця рядок додається до PATH. Якщо я закрию і відкрию командний рядок, то новий рядок не знаходиться в PATH.

Як я можу постійно оновлювати PATH з командного рядка для всіх процесів у майбутньому, а не лише для поточного процесу?

Я не хочу цього робити, перейшовши до Властивості системи → Додатково → Змінні середовища та оновіть PATH там.

Ця команда повинна бути виконана з програми Java (дивіться моє інше питання ).


5
Використовуючи повноваження, це досить просто stackoverflow.com/questions/714877/… . Використовуючи cmd, я не впевнений. Можливо, вам доведеться якось змінити реєстр або якось потягнути в .net збірку.
Остін Холмс

1
Як я вже говорив, я повинен це робити з програми Java. Я думав просто виконати якусь команду cmd useng java'sRuntime.getRuntime().exec("my command");
vale4674

Відповіді:


43

Документацію про те, як це зробити, можна знайти на MSDN . Ключовий екстракт:

Щоб програмно додати або змінити змінні системного середовища, додайте їх до ключа реєстру HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ Environment , а потім транслюйте WM_SETTINGCHANGEповідомлення з lParam, встановленим у рядок "Environment". Це дозволяє програмам, таким як оболонка, збирати ваші оновлення.

Зауважте, що для вашої програми потрібні підвищені права адміністратора, щоб мати змогу змінювати цей ключ.

Ви вказуєте в коментарях, що ви б раді змінити лише середовище для кожного користувача. Зробіть це, відредагувавши значення в HKEY_CURRENT_USER \ Environment . Як і раніше, переконайтеся, що ви транслювали WM_SETTINGCHANGEповідомлення.

Ви повинні мати можливість це зробити з програми Java досить легко, використовуючи класи реєстру JNI.


1
Так, використовуючи класи реєстру JNI. Більш важливим питанням є те, що ваш додаток, ймовірно, не працює підвищеним. Чи знаєте ви, як змусити це зробити? Якщо ви хочете, щоб невелика частина вашого додатка працювала підвищеною (тобто просто щоб зробити цю зміну), тоді найпростішим рішенням є дуже простий додаток C ++, який виконує завдання, позначений маніфестом програми, а потім виконується як окремий процес, який провокує діалог UAC.
Девід Геффернан

1
Ви також можете редагувати, HKEY_CURRENT_USER\Environmentщоб уникнути вимоги висоти.
кічік

@David Heffernan Так, тільки ця річ повинна працювати піднесено. Отже, ваша пропозиція - написати програму C ++ та виконати її з моєї програми Java? Ви можете надати мені якийсь приклад код або посилання про те, як це зробити?
vale4674

Так. Так, як сказав Девід. Тільки ти не піднімаєшся. Я також повинен зазначити, що це змінить середовище лише для поточного користувача.
kichik

Вам потрібно розділити це на окремий процес, щоб ви примусили діалогове вікно UAC лише при зміні системи PATH. Він просто потребує простого додатка C ++ з кількома читаннями і записом реєстру, а за ними - SendMessage. Встановіть requestedExecutionLevelдля requireAdministratorв додатку маніфесту.
Девід Геффернан

145

Ви можете використовувати:

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

Однак, setxурізає збережений рядок до 1024 байтів, потенційно пошкодивши PATH.

/Mзмінить PATHв, HKEY_LOCAL_MACHINEа не HKEY_CURRENT_USER. Іншими словами, замість користувача - системна змінна. Наприклад:

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

Ви повинні пам’ятати, що новий PATH не видно у вашому поточному cmd.exe.

Але якщо заглянути в реєстр чи на новий cmd.exeз ним, "set p"ви зможете побачити нове значення.


2
Чи є спосіб використовувати setxдля зміни шляху машини замість шляху користувача?
Корі Огберн

4
З тут ви можете сказати , що це можна було б встановити змінну не тільки для поточного користувача , але для машини, використовуючи /mв кінці команди, на Windows Xp і 7. Я не пробував , хоча.
пані

1
Я отримав помилку під час виконання setxкоманди "Параметр за замовчуванням не дозволений більше" 2 "часу" Як його обійти?
Нам Г ВУ

12
@KilgoreCod коментарі: Я застерігаю проти використання команди: У багатьох (більшості?) Установок в наші дні змінна PATH буде тривалою - setx обріже збережену рядок до 1024 байтів, потенційно пошкодивши PATH (див. Дискусію тут superuser.com/ q / 812754 ).
beresfordt

2
Я намагаюся відлучити шлях, який вже перевищує 1200 байт. будь-який інший спосіб замість setx?
lawphotog

37

Я застерігаю проти використання команди

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

змінити змінну PATH через "особливість" її реалізації. У багатьох (більшості?) Установок сьогодні ця змінна буде тривалою - setxобрізає збережену рядок до 1024 байтів, потенційно пошкоджуючи PATH (див. Дискусію тут ).

( Я спеціально зареєструвався, щоб позначити цю проблему, і тому мені не вистачає репутації сайту, щоб безпосередньо коментувати відповідь, опубліковану 2 травня '12 року. Моя подяка beresfordt за те, що вони додали такий коментар )


9

Цей скрипт 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десь у вашому поточному шляху. Зауважте, що в цих прикладах у мене не було прав адміністратора , тому зміни стосувалися лише дерева реєстру мого локального користувача:

> 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/


4

Для довідки, для тих, хто шукає, як змінити шлях за допомогою коду, я цитую корисну публікацію програміста Delphi з цієї веб-сторінки: http://www.tek-tips.com/viewthread.cfm?qid=686382

TonHu (програміст) 22 жовтня 03 17:57 Я знайшов, де я прочитав оригінальну публікацію, це тут: http://news.jrsoftware.org/news/innosetup.isx/msg02129 ....

Виписка того, що вам знадобиться, це:

Ви повинні вказати рядок "Навколишнє середовище" в LParam. У Delphi ви зробите це так:

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

Це запропонував Джордан Рассел, http://www.jrsoftware.org , автор (ao) InnoSetup, ("Inno Setup - це безкоштовний інсталятор для програм Windows. Вперше запроваджений в 1997 році, Inno Setup сьогодні конкурує і навіть перевершує багатьох комерційні інсталятори в наборі функцій та стабільності. ") (Я просто хотів би, щоб більше людей використовувало InnoSetup)

HTH


Ви повинні змінити реєстр. Крім того, акторський склад для Integer поганий. Віддайте замість LPARAM 64-бітну сумісність.
Девід Геффернан


4

У корпоративної мережі, де користувач має обмежений доступ і використовує портативні програми, є такі хитрощі командного рядка:

  1. Запит змінних користувача ENV: reg query "HKEY_CURRENT_USER\Environment". Використовуйте "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"для LOCAL_MACHINE.
  2. Додати нову змінну користувача ENV: reg add "HKEY_CURRENT_USER\Environment" /v shared_dir /d "c:\shared" /t REG_SZ. Використовувати REG_EXPAND_SZдля шляхів, що містять інші змінні %%.
  3. Видалити існуючу змінну ENV: reg delete "HKEY_CURRENT_USER\Environment" /v shared_dir.

3

Цей скрипт http://www.autohotkey.com/board/topic/63210-modify-system-path-gui/

включає всі необхідні дзвінки API API, які можна відновити для ваших потреб. Це насправді графічний інтерфейс AutoHotkey, щоб легко змінити PATH системи. Потрібно запускатись як адміністратор.


Прочитайте питання. Знову.
jiggunjer

Чудовий сценарій. Я використовую HotKey, але не знаю, як і що мені потрібно зробити, щоб додати сценарій до нього. Чи можете ви запропонувати допомогу, запропонувати посилання або пояснити, що потрібно зробити?
jwzumwalt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.