webentwicklung-frage-antwort-db.com.de

Wie ändere ich die Umgebungsvariable PATH, wenn ich ein Inno Setup-Installationsprogramm ausführe?

Mit Inno Setup können Sie Umgebungsvariablen über die Abschnitte [Registry] festlegen (indem Sie den Registrierungsschlüssel festlegen, der der Umgebungsvariablen entspricht).

Manchmal möchten Sie jedoch nicht nur eine Umgebungsvariable festlegen. Oft möchten Sie es ändern. Beispiel: Bei der Installation kann es sinnvoll sein, der Umgebungsvariablen PATH ein Verzeichnis hinzuzufügen oder daraus zu entfernen.

Wie kann ich die Umgebungsvariable PATH in InnoSetup ändern?

59
bandana

Der Pfad im angegebenen Registrierungsschlüssel ist ein Wert vom Typ REG_EXPAND_SZ. Wie in der Inno Setup-Dokumentation für den Abschnitt [Registry] angegeben, können Elemente an folgende Elemente angehängt werden:

Für einen Wert vom Typ string, expandsz oder multisz können Sie eine spezielle Konstante mit dem Namen {olddata} in diesem Parameter. {olddata} wird durch die vorherigen Daten des Registrierungswerts ersetzt. Das {olddata} Konstante kann nützlich sein, wenn Sie eine Zeichenfolge an einen vorhandenen Wert anhängen müssen, z. B. {olddata};{app}. Wenn der Wert nicht vorhanden ist oder der vorhandene Wert kein Zeichenfolgentyp ist, wird {olddata} Konstante wird stillschweigend entfernt.

So anhängen auf den Pfad eines Registrierungs Abschnitt ähnlich wie diese verwendet werden können:

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

dies würde das Verzeichnis "C:\foo" an den Pfad anhängen.

Dies würde sich leider wiederholen, wenn Sie ein zweites Mal installieren, was ebenfalls behoben werden sollte. Ein Check -Parameter mit einer in Pascal-Skript codierten Funktion kann verwendet werden, um zu überprüfen, ob der Pfad tatsächlich erweitert werden muss:

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

Diese Funktion liest den ursprünglichen Pfadwert und prüft, ob das angegebene Verzeichnis bereits enthalten ist. Dazu werden Semikolonzeichen vorangestellt und angehängt, mit denen Verzeichnisse im Pfad voneinander getrennt werden. Um die Tatsache zu berücksichtigen, dass das gesuchte Verzeichnis das erste oder letzte Element sein kann, werden Semikolonzeichen vorangestellt und ebenfalls an den ursprünglichen Wert angehängt:

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

Beachten Sie, dass Sie möglicherweise Konstanten erweitern müssen, bevor Sie sie als Parameter an die Prüffunktion übergeben. Weitere Informationen finden Sie in der Dokumentation.

Das Entfernen dieses Verzeichnisses aus dem Pfad während der Deinstallation kann auf ähnliche Weise erfolgen und wird dem Leser als Übung überlassen.

77
mghie

Sie können das modpath.iss -Skript von LegRoom.net in Ihrer InnoSetup-Skriptdatei verwenden:

#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

Ich hatte das gleiche Problem, aber trotz der obigen Antworten habe ich eine benutzerdefinierte Lösung gefunden, die ich Ihnen gerne mitteilen möchte.

Zunächst habe ich die Datei environment.iss Mit zwei Methoden erstellt - eine zum Hinzufügen des Pfads zur Umgebungsvariablen Path und eine zum Entfernen:

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

Referenz: RegQueryStringValue , RegWriteStringValue

Jetzt in der .iss-Hauptdatei könnte ich diese Datei einfügen und auf die 2 Ereignisse warten (mehr über Ereignisse erfahren Sie in Ereignisfunktionen Abschnitt in der Dokumentation), CurStepChanged, um den Pfad nach der Installation hinzuzufügen und CurUninstallStepChanged, um es zu entfernen, wenn der Benutzer eine Anwendung deinstalliert. Im folgenden Beispielskript wird das Verzeichnis bin hinzugefügt/entfernt (relativ zum Installationsverzeichnis):

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

Referenz: ExpandConstant

Hinweis Nr. 1 : Installieren Sie den Schritt "Pfad hinzufügen" nur einmal (stellt die Wiederholbarkeit der Installation sicher).

Hinweis 2 : Deinstallationsschritt entfernt nur ein Vorkommen des Pfads aus der Variablen.

Bonus : Installationsschritt mit Checkbox "Add to PATH variable".

Inno Setup - Add to PATH variable

Um einen Installationsschritt hinzuzufügen, aktivieren Sie das Kontrollkästchen "Zur PATH-Variablen hinzufügen" Definieren Sie eine neue Aufgabe im Abschnitt [Tasks] (Standardmäßig aktiviert):

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

Dann können Sie es in CurStepChanged überprüfen:

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

Das NeedsAddPath in die Antwort von @mghie prüft nicht das abschließende \ und Briefkasten. Repariere es.

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

Hier ist eine vollständige Lösung für das Problem, bei der die Groß- und Kleinschreibung ignoriert, geprüft wird, ob der Pfad mit \ Endet, und die Konstanten im Parameter erweitert werden:

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