-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpath.iss
More file actions
205 lines (186 loc) · 5.49 KB
/
Copy pathpath.iss
File metadata and controls
205 lines (186 loc) · 5.49 KB
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
198
199
200
201
202
203
204
205
// PATH management extension for the Inno Setup installer generatior
// Version: 1.1
// 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 LocateRegistry(var root: Integer; var entry: String);
begin
if IsAdminInstallMode then root := HKLM else root := HKCU;
entry := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
end;
procedure InstallPaths(s: TSetupStep);
var
uninstaller: String;
root: Integer;
paths: Paths;
begin
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
LocateRegistry(root, uninstaller);
RegWriteStringValue(root, uninstaller, 'AddedSystemPaths', MergePaths(addSys)); // Remember added system paths
RegWriteStringValue(root, 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
root: Integer;
path, uninstaller: String;
paths, usrPaths, sysPaths: Paths;
begin
path := '';
LocateRegistry(root, uninstaller);
RegQueryStringValue(root, uninstaller, 'AddedSystemPaths', path);
if path <> '' then begin
sysPaths := SplitPaths(path);
paths := GetSysPaths;
SubtractPaths(paths, sysPaths);
SetSysPaths(paths);
end;
path := '';
RegQueryStringValue(root, 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
if s = usUninstall then RevertPaths(s); { Include this call upon rolling out the custom CurUninstallStepChanged() procedure }
end;