Как обновить переменную PATH постоянно из cmd? Окна


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

эта команда должна быть выполнена из java-приложения (my other вопрос).

7 111

7 ответов:

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

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

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

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

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

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

однако, setx будет усекать сохраненную строку до 1024 байт, потенциально повреждая путь.

/M изменить PATH на HKEY_LOCAL_MACHINE вместо HKEY_CURRENT_USER. Другими словами, переменная системы, а не пользователя. Например:

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

вы должны иметь в виду, что новый путь не виден в текущем cmd.exe.

но если вы посмотрите в реестре или на новый cmd.exe С "set p" вы можете увидеть новое значение.

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

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

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

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

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

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

Тонху (программист) 22 окт 03 17: 57 я нашел, где я читал оригинал сообщение, оно здесь: http://news.jrsoftware.org/news/innosetup.isx/msg02129....

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

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

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

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

HTH

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

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

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

  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.