如何在运行Inno Setup Installer时修改PATH环境variables?
Inno Setup允许您通过[Registry]部分设置环境variables(通过设置对应于环境variables的registry项)
但是,有时你不只是想设置一个环境variables。 通常情况下,你想修改它。 例如:安装时,可能需要向/从PATH环境variables添加/删除目录。
如何从InnoSetup中修改PATH环境variables?
您提供的registry项中的path是REG_EXPAND_SZ
types的值。 正如[registry]部分的Inno安装文档所述,有一种将元素附加到这些文件的方法:
对于
string
,expandsz
或multisz
types的值,可以在此参数中使用一个名为{olddata}
的特殊常量。{olddata}
被replace为registry值的以前的数据。 如果您需要将string附加到现有值(例如{olddata};{app}
,{olddata}
常量可能会很有用。 如果该值不存在或者现有值不是stringtypes,则会默认删除{olddata}
常量。
所以要追加到path可能会使用类似于此的registry部分:
[Registry] Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \ ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};C:\foo"
这会将“C:\ foo”目录追加到path中。
不幸的是,当你第二次安装的时候会重复这个问题,这个问题也应该修复。 带有用Pascal脚本编码的函数的Check
参数可用于检查path确实是否需要展开:
[Registry] Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \ ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};C:\foo"; \ Check: NeedsAddPath('C:\foo')
该函数读取原始path值并检查给定目录是否已包含在其中。 要这样做,它前缀和附加分号字符是用来分隔path中的目录。 为了说明search的目录可能是第一个或最后一个元素,事实上分号字符被预置并附加到原始值:
[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;
请注意,在将它们作为parameter passing给检查函数之前,您可能需要扩展常量,请参阅文档以获取详细信息。
在卸载过程中从path中删除这个目录可以以类似的方式完成,并作为读者的练习。
您可以在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"
NeedsAddPath
的答案中的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;
我有同样的问题,但尽pipe上面的答案,我已经结束了一个自定义的解决scheme,我想分享给你。
首先我创build了两个方法的environment.iss
文件 – 一个用于添加path到环境的Pathvariables,第二个删除它:
[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
在安装后添加path, 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 :安装步骤添加path只有一次(确保安装的可重复性)。
注#2 :卸载步骤只从variables中删除一个path。
奖励 :安装步骤checkbox“添加到PATHvariables” 。
添加安装步骤checkbox“添加到PATHvariables”在[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;
这是一个完全解决问题的方法,忽略大小写,检查是否存在以\
结尾的path,还扩展了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;