How to change PATH environment variable when starting Inno Setup Installer?

Inno Setup allows you to set environment variables through [Registry] sections (by setting the registry key corresponding to the environment variable)

However, sometimes you do not just want to set an environment variable. Often you want to change it. For example: during installation, you can add / remove a directory to / from the PATH environment variable.

How to change PATH environment variable from InnoSetup?

+60
environment-variables inno-setup
Jul 21 2018-10-21T00:
source share
5 answers

The path in the registry key you specified is a value of type REG_EXPAND_SZ . Since the Inno Setup documentation for the [Registry] section says that there is a way to add elements to them:

In a value of type string , expandsz or multisz you can use a special constant named {olddata} in this parameter. {olddata} is replaced with the previous registry value data. The constant {olddata} can be useful if you need to add a string to an existing value, for example, {olddata};{app} . If the value does not exist or the existing value is not a string type, the constant {olddata} silently deleted.

So, to add to the path, you can use a registry key similar to this:

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

which will add the directory "C: \ foo" to the path.

Unfortunately, this will be repeated when installing the second time, which should also be fixed. The Check parameter with a function encoded in a Pascal script can be used to check whether the path really needs to be expanded:

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

This function reads the original value of the path and checks to see if the given directory contains it. To do this, it adds and adds semicolons, which are used to separate directories in a path. To take into account the fact that the search directory can be the first or last character of the semicolon, it is added and added to the original value:

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

Note that you may need to expand the constants before passing them as a parameter to the validation function. See the documentation for more details.

Removing this directory from the path during deletion can be done in a similar way and left as an exercise for the reader.

+77
Aug 07 '10 at 17:32
source share

You can use the Legroom.net modpath.iss script in the InnoSetup script file:

 #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
Apr 01 2018-12-12T00:
source share

I had the same problem, but despite the answers above, I found a non-standard solution and would like to share it with you.

First of all, I created an environment.iss file with two methods - one to add the path to the environment path variable, and the second to delete it:

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

Reference: RegQueryStringValue , RegWriteStringValue

Now, in the main .iss file, I could include this file and listen to 2 events (for more information on events, see the section Event Functions in the documentation), CurStepChanged add the path after installation, and CurUninstallStepChanged to remove it when the user uninstalls the application. In the example script below, add / remove the bin directory (relative to the installation directory):

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

Link: ExpandConstant

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

Note # 2 : The delete step removes only one path entry from the variable.

Bonus : installation step with the "Add to PATH" checkbox.

Inno Setup - Add to PATH variable

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

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

Then you can check this in the CurStepChanged event:

 procedure CurStepChanged(CurStep: TSetupStep); begin if (CurStep = ssPostInstall) and IsTaskSelected('envPath') then EnvAddPath(ExpandConstant('{app}') +'\bin'); end; 
+12
Oct 06 '17 at 15:21
source share

NeedsAddPath in response from @mghie does not check the final \ and letter case. Correct 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; 
+7
Apr 01 2018-12-12T00:
source share

Here is a complete solution to a problem that ignores the shell, checks for the existence of a path ending in \ , and also extends constants in 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
Jul 30 '15 at 20:57
source share



All Articles