Как при установке своей программы прописать путь к ней в в переменную окружения 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 для анализа текстовых файлов