Как изменить переменную среды PATH при запуске установщика Inno Setup? - PullRequest
58 голосов
/ 22 июля 2010

Inno Setup позволяет устанавливать переменные среды через разделы [Registry] (путем установки ключа реестра, соответствующего переменной среды)

Однако иногда вы просто не хотите устанавливать переменную окружения. Часто вы хотите изменить это. Например: после установки можно добавить / удалить каталог в / из переменной среды PATH.

Как я могу изменить переменную среды PATH из InnoSetup?

Ответы [ 5 ]

77 голосов
/ 07 августа 2010

Путь в ключе реестра, который вы указали, имеет значение типа REG_EXPAND_SZ.Как указано в документации Inno Setup для раздела [Registry] , есть способ добавить элементы к ним:

На string, expandsz или multisz введите значение, вы можете использовать специальную константу с именем {olddata} в этом параметре.{olddata} заменяется предыдущими данными значения реестра.Константа {olddata} может быть полезна, если вам нужно добавить строку к существующему значению, например, {olddata};{app}.Если значение не существует или существующее значение не является строковым типом, константа {olddata} удаляется без вывода сообщений.

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

[Registry]
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \
    ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};C:\foo"

, который добавляет каталог "C: \ foo" к пути.

К сожалению, это будет повторяться при установке во второй раз, что также должно быть исправлено.Параметр Check с функцией, закодированной в скрипте Pascal, можно использовать для проверки необходимости расширения пути:

[Registry]
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \
    ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};C:\foo"; \
    Check: NeedsAddPath('C:\foo')

Эта функция считывает исходное значение пути и проверяет, является ли данный каталогуже содержится в нем.Для этого он добавляет и добавляет точки с запятой, которые используются для разделения каталогов в пути.Чтобы учесть тот факт, что искомый каталог может быть первым или последним элементом, точки с запятой добавляются и добавляются к исходному значению, а также:

[Code]

function NeedsAddPath(Param: string): boolean;
var
  OrigPath: string;
begin
  if not RegQueryStringValue(HKEY_LOCAL_MACHINE,
    'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
    'Path', OrigPath)
  then begin
    Result := True;
    exit;
  end;
  { look for the path with leading and trailing semicolon }
  { Pos() returns 0 if not found }
  Result := Pos(';' + Param + ';', ';' + OrigPath + ';') = 0;
end;

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

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

17 голосов
/ 01 апреля 2012

Вы можете использовать сценарий modpath.iss LegRoom.net в своем файле сценария InnoSetup:

#define MyTitleName "MyApp" 

[Setup]
ChangesEnvironment=yes

[CustomMessages]
AppAddPath=Add application directory to your environmental path (required)

[Files]
Source: "install\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs; 

[Icons]
Name: "{group}\{cm:UninstallProgram,{#MyTitleName}}"; Filename: "{uninstallexe}"; Comment: "Uninstalls {#MyTitleName}"
Name: "{group}\{#MyTitleName}"; Filename: "{app}\{#MyTitleName}.EXE"; WorkingDir: "{app}"; AppUserModelID: "{#MyTitleName}"; Comment: "Runs {#MyTitleName}"
Name: "{commondesktop}\{#MyTitleName}"; Filename: "{app}\{#MyTitleName}.EXE"; WorkingDir: "{app}"; AppUserModelID: "{#MyTitleName}"; Comment: "Runs {#MyTitleName}"

[Registry]
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}"

[Tasks]
Name: modifypath; Description:{cm:AppAddPath};   

[Code]

const
    ModPathName = 'modifypath';
    ModPathType = 'system';

function ModPathDir(): TArrayOfString;
begin
    setArrayLength(Result, 1)
    Result[0] := ExpandConstant('{app}');
end;

#include "modpath.iss"
10 голосов
/ 06 октября 2017

У меня была та же проблема, но, несмотря на ответы, приведенные выше, я нашел собственное решение и хотел бы поделиться им с вами.

Прежде всего, я создал environment.issфайл с двумя методами - один для добавления пути к переменной Path * среды, а второй для его удаления:

[Code]
const EnvironmentKey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment';

procedure EnvAddPath(Path: string);
var
    Paths: string;
begin
    { Retrieve current path (use empty string if entry not exists) }
    if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths)
    then Paths := '';

    { Skip if string already found in path }
    if Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';') > 0 then exit;

    { App string to the end of the path variable }
    Paths := Paths + ';'+ Path +';'

    { Overwrite (or create if missing) path environment variable }
    if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths)
    then Log(Format('The [%s] added to PATH: [%s]', [Path, Paths]))
    else Log(Format('Error while adding the [%s] to PATH: [%s]', [Path, Paths]));
end;

procedure EnvRemovePath(Path: string);
var
    Paths: string;
    P: Integer;
begin
    { Skip if registry entry not exists }
    if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) then
        exit;

    { Skip if string not found in path }
    P := Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';');
    if P = 0 then exit;

    { Update path variable }
    Delete(Paths, P - 1, Length(Path) + 1);

    { Overwrite path environment variable }
    if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths)
    then Log(Format('The [%s] removed from PATH: [%s]', [Path, Paths]))
    else Log(Format('Error while removing the [%s] from PATH: [%s]', [Path, Paths]));
end;

Ссылка: RegQueryStringValue, RegWriteStringValue

Теперь в основном файле .iss я мог бы включить этот файл и прослушать 2 события (подробнее о событиях вы можете узнать в разделе Функции событий в документации),CurStepChanged для добавления пути после установки и CurUninstallStepChanged для его удаления при удалении пользователем приложения.В приведенном ниже примере сценария добавьте / удалите каталог bin (относительно каталога установки):

#include "environment.iss"

[Setup]
ChangesEnvironment=true

; More options in setup section as well as other sections like Files, Components, Tasks...

[Code]
procedure CurStepChanged(CurStep: TSetupStep);
begin
    if CurStep = ssPostInstall 
     then EnvAddPath(ExpandConstant('{app}') +'\bin');
end;

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
    if CurUninstallStep = usPostUninstall
    then EnvRemovePath(ExpandConstant('{app}') +'\bin');
end;

Ссылка: ExpandConstant

Примечание# 1 : шаг установки добавить путь только один раз (обеспечивает повторяемость установки).

Примечание # 2 : шаг удаления удаляет только одно вхождение пути из переменной.

Бонус : шаг установки с флажком «Добавить в переменную PATH» .

Inno Setup - Add to PATH variable

Чтобы добавить шаг установки с флажком «Добавить в переменную PATH» определить новое задание в разделе [Tasks] (по умолчанию установлено):

[Tasks]
Name: envPath; Description: "Add to PATH variable" 

Затем вы можете проверить его в CurStepChangedсобытие:

procedure CurStepChanged(CurStep: TSetupStep);
begin
    if (CurStep = ssPostInstall) and IsTaskSelected('envPath')
    then EnvAddPath(ExpandConstant('{app}') +'\bin');
end;
7 голосов
/ 01 апреля 2012

NeedsAddPath в ответ @ mghie не проверяет конечный \ и регистр букв. Исправь это.

function NeedsAddPath(Param: string): boolean;
var
  OrigPath: string;
begin
  if not RegQueryStringValue(
    HKEY_LOCAL_MACHINE,
    'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
    'Path', OrigPath)
  then begin
    Result := True;
    exit;
  end;
  { look for the path with leading and trailing semicolon }
  { Pos() returns 0 if not found }
  Result :=
    (Pos(';' + UpperCase(Param) + ';', ';' + UpperCase(OrigPath) + ';') = 0) and
    (Pos(';' + UpperCase(Param) + '\;', ';' + UpperCase(OrigPath) + ';') = 0); 
end;
2 голосов
/ 30 июля 2015

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

function NeedsAddPath(Param: string): boolean;
var
  OrigPath: string;
  ParamExpanded: string;
begin
  //expand the setup constants like {app} from Param
  ParamExpanded := ExpandConstant(Param);
  if not RegQueryStringValue(HKEY_LOCAL_MACHINE,
    'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
    'Path', OrigPath)
  then begin
    Result := True;
    exit;
  end;
  // look for the path with leading and trailing semicolon and with or without \ ending
  // Pos() returns 0 if not found
  Result := Pos(';' + UpperCase(ParamExpanded) + ';', ';' + UpperCase(OrigPath) + ';') = 0;  
  if Result = True then
     Result := Pos(';' + UpperCase(ParamExpanded) + '\;', ';' + UpperCase(OrigPath) + ';') = 0; 
end;
...