development

Inno Setup Installer를 실행할 때 PATH 환경 변수를 어떻게 수정합니까?

big-blog 2020. 12. 4. 19:45
반응형

Inno Setup Installer를 실행할 때 PATH 환경 변수를 어떻게 수정합니까?


Inno Setup에서는 [Registry] 섹션을 통해 환경 변수를 설정할 수 있습니다 (환경 변수에 해당하는 레지스트리 키 설정).

그러나 때로는 환경 변수를 설정하고 싶지 않을 때도 있습니다. 종종 수정하고 싶을 때가 있습니다. 예 : 설치시 PATH 환경 변수에 디렉토리를 추가 / 제거 할 수 있습니다.

InnoSetup 내에서 PATH 환경 변수를 어떻게 수정할 수 있습니까?


제공 한 레지스트리 키의 경로는 유형 값입니다 REG_EXPAND_SZ. [Registry] 섹션에 대한 Inno Setup 문서에 따르면 여기에 요소를 추가하는 방법이 있습니다.

켜짐 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"디렉토리를 추가합니다.

불행히도 이것은 당신이 두 번째로 설치할 때 반복 될 것입니다. CheckPascal 스크립트로 코딩 된 함수가 있는 매개 변수를 사용하여 경로를 실제로 확장해야하는지 여부를 확인할 수 있습니다.

[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;

check 함수에 매개 변수로 전달하기 전에 상수를 확장해야 할 수도 있습니다. 자세한 내용은 설명서를 참조하십시오.

제거 중에 경로에서이 디렉토리를 제거하는 것은 유사한 방식으로 수행 할 수 있으며 독자를위한 연습으로 남겨 둡니다.


InnoSetup 스크립트 파일에서 LegRoom.net의 modpath.iss 스크립트를 사용할 수 있습니다 .

#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"

나는 같은 문제가 있었지만 위의 답변에도 불구하고 맞춤형 솔루션으로 끝났으며 귀하와 공유하고 싶습니다.

우선 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

Note #1: Install step add path only once (ensures repeatability of the installation).

Note #2: Uninstall step remove only one occurrence of the path from variable.

Bonus: Installation step with checkbox "Add to PATH variable".

Inno Setup - Add to PATH variable

To add installation step with checkbox "Add to PATH variable" define new task in [Tasks] section (checked by default):

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

Then you can check it in CurStepChanged event:

procedure CurStepChanged(CurStep: TSetupStep);
begin
    if (CurStep = ssPostInstall) and IsTaskSelected('envPath')
    then EnvAddPath(ExpandConstant('{app}') +'\bin');
end;

The NeedsAddPath in the answer by @mghie doesn't check trailing \ and letter case. Fix it.

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;

Here is a complete solution to the problem that ignores casing, checks for existence of path ending with \ and also expands the constants in the param:

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;

참고URL : https://stackoverflow.com/questions/3304463/how-do-i-modify-the-path-environment-variable-when-running-an-inno-setup-install

반응형