web-dev-qa-db-ja.com

Inno Setup Installerを実行しているときにPATH環境変数を変更するにはどうすればよいですか?

Inno Setupでは、[Registry]セクションを介して環境変数を設定できます(環境変数に対応するレジストリキーを設定することにより)

ただし、環境変数を設定したくない場合があります。多くの場合、あなたはそれを修正したい。たとえば、インストール時に、PATH環境変数にディレクトリを追加したり、PATH環境変数からディレクトリを削除したりできます。

InnoSetup内からPATH環境変数を変更するにはどうすればよいですか?

59
bandana

指定したレジストリキーのパスは、REG_EXPAND_SZタイプの値です。 [Registry]セクションのInno Setupドキュメントには、それらに要素を追加する方法があります:

stringexpandsz、または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」ディレクトリを追加します。

残念ながら、2回目のインストール時にこれが繰り返されますが、これも修正する必要があります。パスカルスクリプトでコード化された関数を持つCheckパラメーターを使用して、パスを実際に展開する必要があるかどうかを確認できます。

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

チェック関数にパラメータとして渡す前に定数を展開する必要がある場合があることに注意してください。詳細についてはドキュメントを参照してください。

アンインストール中にこのディレクトリをパスから削除することも同様の方法で実行でき、読者の演習として残されます。

77
mghie

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"
17
ecle

私は同じ問題を抱えていましたが、上記の答えにもかかわらず、私はカスタムソリューションになりました。それをあなたと共有したいと思います。

まず、environment.issファイルには2つのメソッドがあります。1つは環境のPath変数にパスを追加し、2つ目はそれを削除します。

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

参照: RegQueryStringValueRegWriteStringValue

メインの.issファイルにこのファイルを含めて、2つのイベント(ドキュメントの Event Functions セクションで学習できるイベントの詳細)をリッスンできます。インストール後にパスを追加するには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:インストール手順はパスを1回だけ追加します(インストールの再現性を確保します)。

注#2:アンインストール手順は、変数からパスの1つの出現のみを削除します。

ボーナス:チェックボックス「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;
12

@ mghieによる答えNeedsAddPathは、末尾の\および大文字と小文字。修理する。

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;
7
Helen Dyakonova

大文字小文字を無視し、\で終わるパスの存在をチェックし、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;
2
vezenkov