-
Notifications
You must be signed in to change notification settings - Fork 0
/
path.iss
197 lines (179 loc) · 5.34 KB
/
path.iss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// PATH management extension for the Inno Setup installer generatior
// Version: 1.0
// Author: Oleg A. Khlybov <fougas@mail.ru>
// Homepage: https://github.com/okhlybov/isx
// License: 3-clause BSD
// Compatible Inno Setup versions: 5.5-6.2
type
PathType = (UserPath, SystemPath);
PathMode = (Append, Prepend);
Paths = array of String;
var
preUsr, postUsr, preSys, postSys, addUsr, addSys : Paths;
procedure AddToPaths(var ps: Paths; s: String);
var
i: Integer;
begin
i := Length(ps);
SetLength(ps, i+1);
ps[i] := ExpandConstant(s);
end;
procedure JoinPaths(var dst: Paths; src: Paths);
var
i: Integer;
begin
for i :=0 to Length(src)-1 do AddToPaths(dst, src[i]);
end;
function MergePaths(paths: Paths): String;
var
i: Integer;
begin
if Length(paths) > 0 then begin
if paths[0] <> '' then result := paths[0];
for i := 1 to Length(paths)-1 do begin
if paths[i] <> '' then result := result + ';' + paths[i];
end;
end;
end;
function SplitPaths(path: String): Paths;
var
first, last, count, total: Integer;
begin
first := 1;
last := 1;
count := 0;
total := Length(path);
while last <= total do begin
while (last <= total) and (path[last] <> ';') do Inc(last);
if last > first then begin
Inc(count);
SetLength(result, count);
result[count-1] := Copy(path, first, last-first);
first := last+1;
Inc(last);
end
else begin
Inc(first);
Inc(last);
end;
end;
end;
procedure RegisterPath(path: String; t: PathType; m: PathMode);
begin
case t of
UserPath:
case m of
Prepend: AddToPaths(preUsr, path);
Append: AddToPaths(postUsr, path);
end;
SystemPath:
case m of
Prepend: AddToPaths(preSys, path);
Append: AddToPaths(postSys, path);
end;
end;
end;
procedure RegisterPaths; forward; // A madnadory user-supplied procedure
const
SysPathKey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
UsrPathKey = 'Environment';
function GetSysPaths: Paths;
var
path: String;
begin
RegQueryStringValue(HKLM, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'PATH', path);
result := SplitPaths(path);
end;
procedure SetSysPaths(paths: Paths);
begin
RegWriteStringValue(HKLM, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'PATH', MergePaths(paths));
end;
function GetUsrPaths: Paths;
var
path: String;
begin
RegQueryStringValue(HKCU, 'Environment', 'PATH', path);
result := SplitPaths(path);
end;
procedure SetUsrPaths(paths: Paths);
begin
RegWriteStringValue(HKCU, 'Environment', 'PATH', MergePaths(paths));
end;
procedure InstallPaths(s: TSetupStep);
var
uninstaller: String;
paths: Paths;
begin
uninstaller := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
if s = ssInstall then begin
RegisterPaths;
// Construct system-wide paths
SetLength(paths, 0);
JoinPaths(paths, preSys);
JoinPaths(paths, GetSysPaths);
JoinPaths(paths, postSys);
SetSysPaths(paths);
SetLength(addSys, 0);
JoinPaths(addSys, preSys);
JoinPaths(addSys, postSys);
// Construct per-user paths
SetLength(paths, 0);
JoinPaths(paths, preUsr);
JoinPaths(paths, GetUsrPaths);
JoinPaths(paths, postUsr);
SetUsrPaths(paths);
SetLength(addUsr, 0);
JoinPaths(addUsr, preUsr);
JoinPaths(addUsr, postUsr);
end else if s = ssPostInstall then begin
RegWriteStringValue(HKLM, uninstaller, 'AddedSystemPaths', MergePaths(addSys)); // Remember added system paths
RegWriteStringValue(HKLM, uninstaller, 'AddedUserPaths', MergePaths(addUsr)); // Remember added user paths
end;
end;
procedure SubtractPaths(var dst: Paths; src: Paths);
var
s, d: Integer;
dst2, src2: Paths;
begin
// Perform case-insensitive comparison
SetLength(src2, Length(src));
for s := 0 to Length(src)-1 do src2[s] := AnsiLowercase(src[s]);
SetLength(dst2, Length(dst));
for d := 0 to Length(dst)-1 do dst2[d] := AnsiLowercase(dst[d]);
for d := 0 to Length(dst2)-1 do begin
for s := 0 to Length(src2)-1 do begin
if dst2[d] = src2[s] then begin dst[d] := ''; end;
end;
end;
end;
procedure RevertPaths(s: TUninstallStep);
var
path, uninstaller: String;
paths, usrPaths, sysPaths: Paths;
begin
uninstaller := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
path := '';
RegQueryStringValue(HKLM, uninstaller, 'AddedSystemPaths', path);
if path <> '' then begin
sysPaths := SplitPaths(path);
paths := GetSysPaths;
SubtractPaths(paths, sysPaths);
SetSysPaths(paths);
end;
path := '';
RegQueryStringValue(HKLM, uninstaller, 'AddedUserPaths', path);
if path <> '' then begin
usrPaths := SplitPaths(path);
paths := GetUsrPaths;
SubtractPaths(paths, usrPaths);
SetUsrPaths(paths);
end;
end;
procedure CurStepChanged(s: TSetupStep);
begin
InstallPaths(s); { Include this call upon rolling out the custom CurStepChanged() procedure }
end;
procedure CurUninstallStepChanged(s: TUninstallStep);
begin
RevertPaths(s); { Include this call upon rolling out the custom CurUninstallStepChanged() procedure }
end;