web-dev-qa-db-fra.com

Comment modifier la variable d'environnement PATH lors de l'exécution d'un programme d'installation d'Inno Setup?

Inno Setup vous permet de définir des variables d'environnement via les sections [Registry] (en définissant une clé de registre qui correspond à la variable d'environnement)

Cependant, parfois, vous ne voulez pas simplement définir une variable d'environnement. Souvent, vous voulez le modifier. Par exemple: lors de l'installation, on peut vouloir ajouter/supprimer un répertoire à/de la variable d'environnement PATH.

Comment puis-je modifier la variable d'environnement PATH à partir d'InnoSetup?

59
bandana

Le chemin d'accès dans la clé de registre que vous avez indiquée est une valeur de type REG_EXPAND_SZ. Comme l'indique la documentation d'Inno Setup pour la section [Registry], il existe un moyen d'ajouter des éléments à ceux-ci:

Sur une valeur de type string, expandsz ou multisz, vous pouvez utiliser une constante spéciale appelée {olddata} dans ce paramètre. {olddata} est remplacé par les données précédentes de la valeur de registre. Le {olddata} constant peut être utile si vous devez ajouter une chaîne à une valeur existante, par exemple, {olddata};{app}. Si la valeur n'existe pas ou si la valeur existante n'est pas un type de chaîne, le {olddata} constante est supprimée en silence.

Donc, pour ajouter au chemin une section de registre similaire à celle-ci peut être utilisée:

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

ce qui ajouterait le répertoire "C:\foo" au chemin.

Malheureusement, cela se répéterait lors de la deuxième installation, ce qui devrait également être corrigé. Un paramètre Check avec une fonction codée en script Pascal peut être utilisé pour vérifier si le chemin a bien besoin d'être développé:

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

Cette fonction lit la valeur du chemin d'origine et vérifie si le répertoire donné y est déjà contenu. Pour ce faire, il ajoute et ajoute des caractères point-virgule qui sont utilisés pour séparer les répertoires du chemin. Pour tenir compte du fait que le répertoire recherché peut être le premier ou le dernier élément, les caractères point-virgule sont également ajoutés et ajoutés à la valeur d'origine:

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

Notez que vous devrez peut-être développer des constantes avant de les passer en paramètre à la fonction de vérification, consultez la documentation pour plus de détails.

La suppression de ce répertoire du chemin lors de la désinstallation peut être effectuée de la même manière et est laissée en exercice au lecteur.

77
mghie

Vous pouvez utiliser le script modpath.iss de LegRoom.net dans votre fichier de script 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"
17
ecle

J'ai eu le même problème mais malgré les réponses ci-dessus, je me suis retrouvé avec une solution personnalisée et je voudrais la partager avec vous.

Tout d'abord, j'ai créé le environment.iss fichier avec 2 méthodes - une pour ajouter un chemin à la variable Path de l'environnement et la seconde pour la supprimer:

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

Référence: RegQueryStringValue , RegWriteStringValue

Maintenant, dans le fichier .iss principal, je pourrais inclure ce fichier et écouter les 2 événements (plus d'informations sur les événements que vous pouvez apprendre dans la section Fonctions d'événement dans la documentation), CurStepChanged pour ajouter un chemin après l'installation et CurUninstallStepChanged pour le supprimer lorsque l'utilisateur désinstalle une application. Dans l'exemple de script ci-dessous, ajoutez/supprimez le répertoire bin (par rapport au répertoire d'installation):

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

Référence: ExpandConstant

Remarque # 1 : Étape d'installation ajouter le chemin d'accès une seule fois (assure la répétabilité de l'installation).

Remarque n ° 2 : l'étape de désinstallation supprime une seule occurrence du chemin de la variable.

Bonus : Étape d'installation avec la case à cocher "Ajouter à la variable PATH".

Inno Setup - Add to PATH variable

Pour ajouter une étape d'installation avec la case à cocher "Ajouter à la variable PATH" définir une nouvelle tâche dans [Tasks] section (cochée par défaut):

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

Ensuite, vous pouvez le vérifier dans l'événement CurStepChanged:

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

Le NeedsAddPath in la réponse de @mghie ne vérifie pas le _ \ et la casse des lettres. Répare le.

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

Voici une solution complète au problème qui ignore la casse, vérifie l'existence d'un chemin se terminant par \ et développe également les constantes dans le paramètre:

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