modpath.pas 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // ----------------------------------------------------------------------------
  2. //
  3. // Inno Setup Ver: 5.4.2
  4. // Script Version: 1.4.2
  5. // Author: Jared Breland <jbreland@legroom.net>
  6. // Homepage: https://www.legroom.net/software
  7. // License: GNU Lesser General Public License (LGPL), version 3
  8. // https://www.gnu.org/licenses/lgpl.html
  9. //
  10. // Script Function:
  11. // Allow modification of environmental path directly from Inno Setup installers
  12. //
  13. // Instructions:
  14. // Copy modpath.iss to the same directory as your setup script
  15. //
  16. // Add this statement to your [Setup] section
  17. // ChangesEnvironment=true
  18. //
  19. // Add this statement to your [Tasks] section
  20. // You can change the Description or Flags
  21. // You can change the Name, but it must match the ModPathName setting below
  22. // Name: modifypath; Description: &Add application directory to your environmental path; Flags: unchecked
  23. //
  24. // Add the following to the end of your [Code] section
  25. // ModPathName defines the name of the task defined above
  26. // ModPathType defines whether the 'user' or 'system' path will be modified;
  27. // this will default to user if anything other than system is set
  28. // setArrayLength must specify the total number of dirs to be added
  29. // Result[0] contains first directory, Result[1] contains second, etc.
  30. // const
  31. // ModPathName = 'modifypath';
  32. // ModPathType = 'user';
  33. //
  34. // function ModPathDir(): TArrayOfString;
  35. // begin
  36. // setArrayLength(Result, 1);
  37. // Result[0] := ExpandConstant('{app}');
  38. // end;
  39. // #include "modpath.iss"
  40. // ----------------------------------------------------------------------------
  41. procedure ModPath();
  42. var
  43. oldpath: String;
  44. newpath: String;
  45. updatepath: Boolean;
  46. pathArr: TArrayOfString;
  47. aExecFile: String;
  48. aExecArr: TArrayOfString;
  49. i, d: Integer;
  50. pathdir: TArrayOfString;
  51. regroot: Integer;
  52. regpath: String;
  53. begin
  54. // Get constants from main script and adjust behavior accordingly
  55. // ModPathType MUST be 'system' or 'user'; force 'user' if invalid
  56. if ModPathType = 'system' then begin
  57. regroot := HKEY_LOCAL_MACHINE;
  58. regpath := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
  59. end else begin
  60. regroot := HKEY_CURRENT_USER;
  61. regpath := 'Environment';
  62. end;
  63. // Get array of new directories and act on each individually
  64. pathdir := ModPathDir();
  65. for d := 0 to GetArrayLength(pathdir)-1 do begin
  66. updatepath := true;
  67. // Modify WinNT path
  68. if UsingWinNT() = true then begin
  69. // Get current path, split into an array
  70. RegQueryStringValue(regroot, regpath, 'Path', oldpath);
  71. oldpath := oldpath + ';';
  72. i := 0;
  73. while (Pos(';', oldpath) > 0) do begin
  74. SetArrayLength(pathArr, i+1);
  75. pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1);
  76. oldpath := Copy(oldpath, Pos(';', oldpath)+1, Length(oldpath));
  77. i := i + 1;
  78. // Check if current directory matches app dir
  79. if pathdir[d] = pathArr[i-1] then begin
  80. // if uninstalling, remove dir from path
  81. if IsUninstaller() = true then begin
  82. continue;
  83. // if installing, flag that dir already exists in path
  84. end else begin
  85. updatepath := false;
  86. end;
  87. end;
  88. // Add current directory to new path
  89. if i = 1 then begin
  90. newpath := pathArr[i-1];
  91. end else begin
  92. newpath := newpath + ';' + pathArr[i-1];
  93. end;
  94. end;
  95. // Append app dir to path if not already included
  96. if (IsUninstaller() = false) AND (updatepath = true) then
  97. newpath := newpath + ';' + pathdir[d];
  98. // Write new path
  99. RegWriteStringValue(regroot, regpath, 'Path', newpath);
  100. // Modify Win9x path
  101. end else begin
  102. // Convert to shortened dirname
  103. pathdir[d] := GetShortName(pathdir[d]);
  104. // If autoexec.bat exists, check if app dir already exists in path
  105. aExecFile := 'C:\AUTOEXEC.BAT';
  106. if FileExists(aExecFile) then begin
  107. LoadStringsFromFile(aExecFile, aExecArr);
  108. for i := 0 to GetArrayLength(aExecArr)-1 do begin
  109. if IsUninstaller() = false then begin
  110. // If app dir already exists while installing, skip add
  111. if (Pos(pathdir[d], aExecArr[i]) > 0) then
  112. updatepath := false;
  113. break;
  114. end else begin
  115. // If app dir exists and = what we originally set, then delete at uninstall
  116. if aExecArr[i] = 'SET PATH=%PATH%;' + pathdir[d] then
  117. aExecArr[i] := '';
  118. end;
  119. end;
  120. end;
  121. // If app dir not found, or autoexec.bat didn't exist, then (create and) append to current path
  122. if (IsUninstaller() = false) AND (updatepath = true) then begin
  123. SaveStringToFile(aExecFile, #13#10 + 'SET PATH=%PATH%;' + pathdir[d], True);
  124. // If uninstalling, write the full autoexec out
  125. end else begin
  126. SaveStringsToFile(aExecFile, aExecArr, False);
  127. end;
  128. end;
  129. end;
  130. end;
  131. // Split a string into an array using passed delimiter.
  132. procedure MPExplode(var Dest: TArrayOfString; Text: String; Separator: String);
  133. var
  134. i: Integer;
  135. begin
  136. i := 0;
  137. repeat
  138. SetArrayLength(Dest, i+1);
  139. if Pos(Separator,Text) > 0 then begin
  140. Dest[i] := Copy(Text, 1, Pos(Separator, Text)-1);
  141. Text := Copy(Text, Pos(Separator,Text) + Length(Separator), Length(Text));
  142. i := i + 1;
  143. end else begin
  144. Dest[i] := Text;
  145. Text := '';
  146. end;
  147. until Length(Text)=0;
  148. end;
  149. procedure CurStepChanged(CurStep: TSetupStep);
  150. var
  151. taskname: String;
  152. begin
  153. taskname := ModPathName;
  154. if CurStep = ssPostInstall then
  155. if IsTaskSelected(taskname) then
  156. ModPath();
  157. end;
  158. procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
  159. var
  160. aSelectedTasks: TArrayOfString;
  161. i: Integer;
  162. taskname: String;
  163. regpath: String;
  164. regstring: String;
  165. appid: String;
  166. begin
  167. // only run during actual uninstall
  168. if CurUninstallStep = usUninstall then begin
  169. // get list of selected tasks saved in registry at install time
  170. appid := '{#emit SetupSetting("AppId")}';
  171. if appid = '' then appid := '{#emit SetupSetting("AppName")}';
  172. regpath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\'+appid+'_is1');
  173. RegQueryStringValue(HKLM, regpath, 'Inno Setup: Selected Tasks', regstring);
  174. if regstring = '' then RegQueryStringValue(HKCU, regpath, 'Inno Setup: Selected Tasks', regstring);
  175. // check each task; if matches modpath taskname, trigger patch removal
  176. if regstring <> '' then begin
  177. taskname := ModPathName;
  178. MPExplode(aSelectedTasks, regstring, ',');
  179. if GetArrayLength(aSelectedTasks) > 0 then begin
  180. for i := 0 to GetArrayLength(aSelectedTasks)-1 do begin
  181. if comparetext(aSelectedTasks[i], taskname) = 0 then
  182. ModPath();
  183. end;
  184. end;
  185. end;
  186. end;
  187. end;
  188. function NeedRestart(): Boolean;
  189. var
  190. taskname: String;
  191. begin
  192. taskname := ModPathName;
  193. if IsTaskSelected(taskname) and not UsingWinNT() then begin
  194. Result := True;
  195. end else begin
  196. Result := False;
  197. end;
  198. end;