Как постоянно обновлять переменную PATH из cmd? Windows - PullRequest
115 голосов
/ 02 декабря 2011

Если я выполню set PATH=%PATH%;C:\\Something\\bin из cmd, а затем выполню echo %PATH%, я вижу, что эта строка добавлена ​​в путь.Если я закрою и открою cmd, этой новой строки нет в PATH.Как я могу постоянно обновлять PATH из cmd для всех процессов в будущем, а не только для текущего процесса?Я не хочу этого делать, перейдя в Свойства системы -> Дополнительно -> Переменные среды и там обновите PATH.

Эта команда должна быть выполнена из Java-приложения (мой другой вопрос ).

Ответы [ 7 ]

143 голосов
/ 02 мая 2012

Вы можете использовать:

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", вы увидите новое значение.

41 голосов
/ 02 декабря 2011

Документацию о том, как это сделать, можно найти на MSDN . Ключевая выдержка такова:

Чтобы программно добавить или изменить системные переменные среды, добавьте их в раздел реестра HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ Environment , а затем отправьте сообщение WM_SETTINGCHANGE с lParam, установленным в строку «Environment». Это позволяет приложениям, таким как оболочка, получать ваши обновления.

Обратите внимание, что для изменения этого ключа вашему приложению потребуются повышенные права администратора.

В комментариях вы указываете, что были бы рады изменить только среду для каждого пользователя. Сделайте это, отредактировав значения в HKEY_CURRENT_USER \ Environment . Как и прежде, убедитесь, что вы передаете сообщение WM_SETTINGCHANGE.

Вы должны быть в состоянии сделать это из вашего Java-приложения достаточно легко, используя классы реестра JNI.

35 голосов
/ 16 июня 2015

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

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

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

( Я подписался специально, чтобы пометить эту проблему, и поэтому у меня нет репутации сайта, чтобы напрямую комментировать ответ, опубликованный 2 мая 12 года. Благодарю beresfordt за добавление такого комментария )

7 голосов
/ 06 февраля 2015

Этот 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/

3 голосов
/ 09 мая 2017

В корпоративной сети, где пользователь имеет только ограниченный доступ и использует переносимые приложения, существуют следующие приемы командной строки:

  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 голосов
/ 24 марта 2013

Для справки, для тех, кто ищет, как изменить путь с помощью кода, я цитирую полезный пост программиста Delphi с этой веб-страницы: http://www.tek -tips.com / viewthread.cfm? Qid = 686382

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

Выдержка из того, что вам нужно, это:

Вы должны указать строку "Environment" в LParam. В Delphi вы бы сделать это так:

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

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

НТН

2 голосов
/ 15 августа 2013

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

включает все необходимые вызовы Windows API, которые могут быть реорганизованы для ваших нужд. На самом деле это графический интерфейс AutoHotkey для простого изменения системного PATH. Необходимо запустить от имени администратора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...