Как при установке своей программы прописать путь к ней в в переменную окружения PATH, чтобы программу можно было запустить из любого каталога? А при удалении программы, соответственно, удалить путь из переменной PATH? При этом необходимо различать системную и пользовательскую переменные PATH.

Есть, конечно, простой способ «в одну строку» с использованием программы setx, для для пользовательской переменной PATH это выглядит так:

setx Path "%Path%;MyPath"

и для системной переменной PATH то же самое с добавлением ключа /M:

setx Path "%Path%;MyPath" /M

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

И все равно нет решения по удалению пути, то есть будет происходить замусоривание PATH и замедление запуска программ.

Поэтому лучше использовать следующие WSH/JScript скрипты, лишенные этих недостатков.

Добавление пути в пользовательскую переменную Path

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

  • Считывает текущее значение переменной Path из реестра (пользовательские переменные находятся здесь HKCU\Environment\Path), основан на Чтение из реестра в скрипте WSH.
  • Проверяет, возможно, этот путь уже добавлен, в этом случае скрипт завершает свою работу.
  • Добавляет путь к значению переменной Path.
  • Сохраняет итоговое значение вызовом SETX. Почему именно через SETX, а не через сохранение значения обратно в реестр? Разница в том, что изменение, сделанное через SETX, начинает работать сразу (для новых процессов, конечно), а изменения, сохранённые через реестр, начнут работать только после выхода-входа пользователя.

Код скрипта user_path_add.js:

var wsh_shell = WScript.CreateObject("WScript.Shell");
var path = wsh_shell.ExpandEnvironmentStrings(WScript.Arguments.Unnamed(0));

var v = "";
try {
    v = wsh_shell.RegRead("HKCU\\Environment\\Path");
}
catch ( e ) {
}

if ( v != "" ) {
    for ( var i = new Enumerator(v.split(";")); !i.atEnd(); i.moveNext()) 
        if ( path.toUpperCase() == i.item().toUpperCase() ) 
            WScript.Quit(0);
    if ( v.charAt(v.length-1) != ";" )
        v += ";";
}
v += path;
if ( wsh_shell.Run("setx Path \"" + v + "\"",0,true) != 0 )
    WScript.Echo("setx failed.");

Пример добавления пути к программе nhsms, установленной в профиль пользователя, из командной строки:

cscript //nologo user_path_add.js "%localappdata%\nhsms"

Этот вариант скрипта не выводит почти никакой информации о своей работе, кроме сообщения в случае ошибки в setx, то есть если путь уже присутствует в PATH или если путь был успешно добавлен в PATH, то в выводе это не отразится, Поэтому если требуется сделать скрипт более информативным, можно добавить вызовы WScript.Echo, которые при запуске через cscript.exe будут выводиться в окне командной строки, а при запуске через wscript.exe — в виде всплывающего окна::

var wsh_shell = WScript.CreateObject("WScript.Shell");
var path = wsh_shell.ExpandEnvironmentStrings(WScript.Arguments.Unnamed(0));

var v = "";
try {
    v = wsh_shell.RegRead("HKCU\\Environment\\Path");
}
catch ( e ) {
}

if ( v != "" ) {
    for ( var i = new Enumerator(v.split(";")); !i.atEnd(); i.moveNext()) 
        if ( path.toUpperCase() == i.item().toUpperCase() ) {
            WScript.Echo("Путь уже присутствует в Path.");
            WScript.Quit(0);
        }
    if ( v.charAt(v.length-1) != ";" )
        v += ";";
}
v += path;
if ( wsh_shell.Run("setx Path \"" + v + "\"",0,true) != 0 )
    WScript.Echo("Ошибка при добавлении пути (setx).");
else
    WScript.Echo("Путь добавлен в Path.");

Удаление пути из пользовательской переменной Path

Скрипт user_path_remove.js для удаления пути из переменной построен аналогично и выполняет следующие действия:

  • Считывает текущее значение переменной Path из реестра (HKCU\Environment\Path).
  • Перебирает пути, занесённые в Path, удаляя заданный путь.
  • Сохраняет итоговое значение вызовом setx, в результате изменение переменной происходит сразу. Если итоговое значение Path оказывается пустым, скрипт дополнительно вызывает reg delete для удаления значения (setx не может удалять значения из реестра, в результате остается переменная с пустым значением).
var wsh_shell = WScript.CreateObject("WScript.Shell"); 
var path = wsh_shell.ExpandEnvironmentStrings(WScript.Arguments.Unnamed(0)); var v = ""; 
try {
    v = wsh_shell.RegRead("HKCU\\Environment\\Path"); 
}
catch ( e ) { } 
if ( v == "" )
    WScript.Quit(0); 
var new_v = ""; 
for ( var i = new Enumerator(v.split(";")); !i.atEnd(); i.moveNext())  
    if ( i.item().length && i.item().toUpperCase() != path.toUpperCase() )      
        new_v += i.item() + ";"; 
if ( new_v != "" ) { 
    if ( wsh_shell.Run(     
    "setx Path \"" + new_v.substr(0,new_v.length-1) + "\" ",0,true) != 0 )     
    WScript.Echo("setx failed."); } 
else { 
    wsh_shell.Run("setx Path \"\" ",0,true); 
    wsh_shell.Run("reg delete HKCU\\Environment /v Path /f ",0,true); 
}

Пример удаления пути программы nhsms, установленной в профиль пользователя, из командной строки, эту строку можно использовать в bat файле:

cscript //nologo user_path_remove.js "%localappdata%\nhsms"

Добавление пути в системную переменную Path

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

  • используется системная переменная PATH из  HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\path
  • вызов SETX с аргументом /M
  • проверка на отсутствие значения Path исключена
  • скрипту требуются административные полномочия (Run As Administrator)

Скрипт system_path_add.js добавления пути в системную переменную PATH:

var wsh_shell = WScript.CreateObject("WScript.Shell");
var path = wsh_shell.ExpandEnvironmentStrings(WScript.Arguments.Unnamed(0));

var v = wsh_shell.RegRead("HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\\path");
for ( var i = new Enumerator(v.split(";")); !i.atEnd(); i.moveNext())
    if ( path.toUpperCase() == i.item().toUpperCase() )
WScript.Quit(0);
if ( v.charAt(v.length-1) != ";" )
    v += ";";
v += path;
if ( wsh_shell.Run("setx /M Path \"" + v + "\"",0,true) != 0 )
    WScript.Echo("setx failed.");

Удаление пути из системной переменной Path

Скрипт system_path_remove.js для удаления указанного пути из системной переменной PATH:

var wsh_shell = WScript.CreateObject("WScript.Shell");
var path = wsh_shell.ExpandEnvironmentStrings(WScript.Arguments.Unnamed(0));

var newv = "";
var v = wsh_shell.RegRead("HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\\path");
for ( var i = new Enumerator(v.split(";")); !i.atEnd(); i.moveNext())
    if ( i.item().length && i.item().toUpperCase() != path.toUpperCase() )
newv += i.item() + ";";

if ( wsh_shell.Run("setx /M path \"" + newv.substr(0,newv.length-1) + "\"",0,true) != 0 )
    WScript.Echo("setx failed.");

Выполнение скриптов из командной строки:

cscript //nologo system_path_add.js "%programfiles(x86)%\nhsms"
cscript //nologo system_path_remove.js "%programfiles(x86)%\nhsms"

И чтобы изменение переменной PATH происходило автоматически при установке/удалении программы через Inno Setup, достаточно добавить несколько строк в проект:

[Files]

...
Source: "user_path_add.js"; DestDir: "{app}"
Source: "user_path_remove.js"; DestDir: "{app}"

[Run]
Filename: "wscript.exe"; Parameters: """{app}\user_path_add.js"" ""{app}"""

[UninstallRun]
Filename: "wscript.exe"; Parameters: """{app}\user_path_remove.js"" ""{app}"""

UPD. В скрипты были добавлены проверки на отсутствие значения Path в реестре HKCU\Environment. В первой версии скрипта такой проверки не было и, если значение Path не существовало, возникало исключение (необработанное).

setx и Windows XP

setx штатно присутствует в Windows, начиная с Windows Vista. setx для Windows XP можно взять из  Windows XP Service Pack 2 Support Tools

Интересно

Использование Setx для анализа текстовых файлов

Скрипт добавления пути в переменную path
Метки:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *