forked from canton7/SyncTrayzor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommon.iss
337 lines (307 loc) · 12.7 KB
/
common.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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
#define AppExeName "SyncTrayzor.exe"
#define AppRoot "..\.."
#define AppSrc AppRoot + "\src\SyncTrayzor"
#define AppBin AppRoot +"\bin\" + Arch + "\Release"
#define AppExe AppBin + "\SyncTrayzor.exe"
#define AppName GetStringFileInfo(AppExe, "ProductName")
#define AppVersion GetVersionNumbersString(AppExe)
#define AppPublisher "SyncTrayzor"
#define AppURL "https://github.com/canton7/SyncTrayzor"
#define AppDataFolder "SyncTrayzor"
#define RunRegKey "Software\Microsoft\Windows\CurrentVersion\Run"
#define DotNetInstallerExe "dotNet472Setup.exe"
#define DonateUrl "https://synctrayzor.antonymale.co.uk/donate"
[Setup]
AppId={{#AppId}
AppName={#AppName} ({#Arch})
AppVersion={#AppVersion}
VersionInfoVersion={#AppVersion}
;AppVerName={#AppName} {#AppVersion}
AppPublisher={#AppPublisher}
AppPublisherURL={#AppURL}
AppSupportURL={#AppURL}
AppUpdatesURL={#AppURL}
DefaultDirName={commonpf}\{#AppName}
DefaultGroupName={#AppName}
AllowNoIcons=yes
OutputDir="."
OutputBaseFilename={#AppName}Setup-{#Arch}
SetupIconFile={#AppSrc}\Icons\default.ico
WizardSmallImageFile=..\icon.bmp
Compression=lzma2/max
;Compression=None
SolidCompression=yes
PrivilegesRequired=admin
CloseApplications=yes
RestartApplications=no
; If we try and close CefSharp.BrowserSubprocess.exe we'll fail - it doesn't respond well
; However if we close *just* SyncTrayzor, that will take care of shutting down CefSharp and syncthing
CloseApplicationsFilter=SyncTrayzor.exe
TouchDate=current
WizardStyle=modern
; We do access user areas, but only as a best-effort attempt to clean up after ourselves
UsedUserAreasWarning=no
#if "x64" == Arch
ArchitecturesInstallIn64BitMode=x64
ArchitecturesAllowed=x64
#endif
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[CustomMessages]
InstallingDotNetFramework=Installing .NET Framework. This might take a few minutes...
DotNetFrameworkFailedToLaunch=Failed to launch .NET Framework Installer with error "%1". Please fix the error then run this installer again.
DotNetFrameworkFailed1602=.NET Framework installation was cancelled. This installation can continue, but be aware that this application may not run unless the .NET Framework installation is completed successfully.
DotNetFrameworkFailed1603=A fatal error occurred while installing the .NET Framework. Please fix the error, then run the installer again.
DotNetFrameworkFailed5100=Your computer does not meet the requirements of the .NET Framework. Please consult the documentation.
DotNetFrameworkFailedOther=The .NET Framework installer exited with an unexpected status code "%1". Please review any other messages shown by the installer to determine whether the installation completed successfully, and abort this installation and fix the problem if it did not.
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Dirs]
Name: "{userappdata}\{#AppDataFolder}"
[Files]
; Near the beginning, as it's extracted first and this makes it cheaper
Source: "..\{#DotNetInstallerExe}"; DestDir: {tmp}; Flags: dontcopy nocompression noencryption
Source: "{#AppBin}\*"; DestDir: "{app}"; Excludes: "*.xml,*.vshost.*,*.config,*.log,*.pdb,FluentValidation.resources.dll,System.Windows.Interactivity.resources.dll,syncthing.exe,data,logs,cef_extensions.pak,d3dcompiler_47.dll,libEGL.dll,libGLESv2.dll,swiftshader/libEGL.dll,swiftshader/libGLESv2.dll"; Flags: ignoreversion recursesubdirs
Source: "{#AppBin}\SyncTrayzor.exe.Installer.config"; DestDir: "{app}"; DestName: "SyncTrayzor.exe.config"; Flags: ignoreversion
Source: "{#AppSrc}\Icons\default.ico"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#AppRoot}\*.md"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#AppRoot}\*.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "vc++\*.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "ucrt\*.dll"; DestDir: "{app}"; Flags: ignoreversion; OnlyBelowVersion: 10.0
Source: "syncthing.exe"; DestDir: "{app}"; DestName: "syncthing.exe"; Flags: ignoreversion
[InstallDelete]
Type: files; Name: "{app}\msvcp120.dll"
Type: files; Name: "{app}\msvcr120.dll"
Type: files; Name: "{app}\vccorlib120.dll"
Type: files; Name: "{app}\*.pdb"
Type: files; Name: "{app}\System.Windows.Interactivity.dll"
[Icons]
Name: "{group}\{#AppName}"; Filename: "{app}\{#AppExeName}"
Name: "{group}\{cm:UninstallProgram,{#AppName}}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Tasks: desktopicon
[Run]
Filename: "{app}\{#AppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall; Parameters: {code:SyncTrayzorStartFlags}; Check: ShouldStartSyncTrayzor
[Code]
var
GlobalRestartRequired: boolean;
function DotNetIsMissing(): Boolean;
var
Exists: Boolean;
Release: Cardinal;
begin
// https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed#minimum-version
Exists := RegQueryDWordValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release', Release);
Result := not Exists or (Release < 461808);
end;
// Adapted from https://blogs.msdn.microsoft.com/davidrickard/2015/07/17/installing-net-framework-4-5-automatically-with-inno-setup/
function InstallDotNet(): String;
var
StatusText: string;
ResultCode: Integer;
begin
StatusText := WizardForm.StatusLabel.Caption;
WizardForm.StatusLabel.Caption := CustomMessage('InstallingDotNetFramework');
WizardForm.ProgressGauge.Style := npbstMarquee;
try
ExtractTemporaryFile('{#DotNetInstallerExe}');
if not Exec(ExpandConstant('{tmp}\{#DotNetInstallerExe}'), '/passive /norestart /showrmui /showfinalerror', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
begin
Result := FmtMessage(CustomMessage('DotNetFrameworkFailedToLaunch'), [SysErrorMessage(ResultCode)]);
end
else
begin
// See https://msdn.microsoft.com/en-us/library/ee942965(v=vs.110).aspx#return_codes
case resultCode of
0: begin
// Successful
end;
1602 : begin
MsgBox(CustomMessage('DotNetFrameworkFailed1602'), mbInformation, MB_OK);
end;
1603: begin
Result := CustomMessage('DotNetFrameworkFailed1603');
end;
1641: begin
GlobalRestartRequired := True;
end;
3010: begin
GlobalRestartRequired := True;
end;
5100: begin
Result := CustomMessage('DotNetFrameworkFailed5100');
end;
else begin
MsgBox(FmtMessage(CustomMessage('DotNetFrameworkFailedOther'), [IntToStr(ResultCode)]), mbError, MB_OK);
end;
end;
end;
finally
WizardForm.StatusLabel.Caption := StatusText;
WizardForm.ProgressGauge.Style := npbstNormal;
end;
end;
procedure BumpInstallCount;
var
FileContents: AnsiString;
InstallCount: integer;
begin
{ Increment the install count in InstallCount.txt if it exists, or create it with the contents '1' if it doesn't }
if LoadStringFromFile(ExpandConstant('{app}\InstallCount.txt'), FileContents) then
begin
InstallCount := StrTointDef(Trim(string(FileContents)), 0) + 1;
end
else
begin
InstallCount := 1;
end;
SaveStringToFile(ExpandConstant('{app}\InstallCount.txt'), IntToStr(InstallCount), False);
end;
procedure URLLabelOnClick(Sender: TObject);
var
ErrorCode: Integer;
begin
ShellExec('open', '{#DonateUrl}', '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
end;
procedure InitializeWizard;
var
URLLabel: TNewStaticText;
begin
URLLabel := TNewStaticText.Create(WizardForm);
URLLabel.Caption := 'Donate';
URLLabel.Cursor := crHand;
URLLabel.Parent := WizardForm;
URLLabel.Font.Style := URLLabel.Font.Style + [fsUnderline];
URLLabel.Font.Color := clBlue;
URLLabel.Top := WizardForm.ClientHeight - URLLabel.Height - 30;
URLLabel.Left := ScaleX(20)
URLLabel.Anchors := [akLeft, akBottom]
URLLabel.OnClick := @URLLabelOnClick;
end;
procedure CurStepChanged(CurStep: TSetupStep);
var
FindRec: TFindRec;
FolderPath: String;
FilePath: String;
ExeConfig: String;
begin
if CurStep = ssInstall then
begin
BumpInstallCount();
{ We might be being run from ProcessRunner.exe, *and* we might be trying to update it. Funsies. Let's rename it (which Windows lets us do) }
DeleteFile(ExpandConstant('{app}\ProcessRunner.exe.old'));
RenameFile(ExpandConstant('{app}\ProcessRunner.exe'), ExpandConstant('{app}\ProcessRunner.exe.old'));
Log(ExpandConstant('Looking for resource files in {app}\*'));
{ Remove resource files. This means that out-of-date languages will be removed, which (as a last-ditch resore) will alert maintainers that something's wrong }
if FindFirst(ExpandConstant('{app}\*'), FindRec) then
begin
try
repeat
if (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0) and (FindRec.Name <> '.') and (FindRec.Name <> '..') then
begin
FolderPath := ExpandConstant('{app}\') + FindRec.Name;
FilePath := FolderPath + '\SyncTrayzor.resources.dll';
if DeleteFile(FilePath) then
begin
Log('Deleted ' + FilePath);
if DelTree(FolderPath, True, False, False) then
Log('Deleted ' + FolderPath);
end;
end;
until not FindNext(FindRec);
finally
FindClose(FindRec);
end;
end;
end
else if CurStep = ssPostInstall then
begin
ExeConfig := ExpandConstant('{param:SyncTrayzorExeConfig}');
if ExeConfig <> '' then
begin
if FileExists(ExeConfig) then
begin
FileCopy(ExeConfig, ExpandConstant('{app}\SyncTrayzor.exe.config'), false);
end
else
begin
MsgBox('Could not find SyncTrayzorExeConfig file: ' + ExeConfig + '. Using default.', mbError, MB_OK);
end
end
end
end;
function CmdLineParamGiven(const Value: String): Boolean;
var
I: Integer;
begin
// Can't use {param}, as it doesn't match flags with no value
Result := False;
for I := 1 to ParamCount do
if CompareText(ParamStr(I), Value) = 0 then
begin
Result := True;
Exit;
end;
end;
function PrepareToInstall(var NeedsRestart: Boolean): String;
begin
// 'NeedsRestart' only has an effect if we return a non-empty string, thus aborting the installation.
// If the installers indicate that they want a restart, this should be done at the end of installation.
// Therefore we set the global 'restartRequired' if a restart is needed, and return this from NeedRestart()
if not CmdLineParamGiven('/SkipDotNetInstall') and DotNetIsMissing() then
begin
Result := InstallDotNet();
end;
end;
function NeedRestart(): Boolean;
begin
Result := GlobalRestartRequired;
end;
function ShouldStartSyncTrayzor(): Boolean;
begin
Result := (not WizardSilent()) or CmdLineParamGiven('/StartSyncTrayzor');
end;
function SyncTrayzorStartFlags(param: String): String;
begin
if WizardSilent() then begin
Result := '-minimized'
end else begin
Result := ''
end;
end;
// We won't be able to find keys for users other than the one running the installer, but try and do
// a best-effort attempt to cleaning ourselves up.
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
keyValueNames: TArrayOfString;
keyValue: String;
i: Integer;
begin
if CurUninstallStep = usPostUninstall then
begin
if RegGetValueNames(HKEY_CURRENT_USER, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run', keyValueNames) then
begin
for i := 0 to GetArrayLength(keyValueNames)-1 do
begin
if Pos('SyncTrayzor', keyValueNames[i]) = 1 then
begin
if RegQueryStringValue(HKEY_CURRENT_USER, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run', keyValueNames[i], keyValue) then
begin
if Pos(ExpandConstant('"{app}\{#AppExeName}"'), keyValue) = 1 then
begin
RegDeleteValue(HKEY_CURRENT_USER, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run', keyValueNames[i]);
end;
end;
end
end;
end;
end;
end;
[UninstallRun]
Filename: "{app}\SyncTrayzor.exe"; Parameters: "--shutdown"; RunOnceId: "ShutdownSyncTrayzor"; Flags: skipifdoesntexist
[UninstallDelete]
Type: files; Name: "{app}\ProcessRunner.exe.old"
Type: files; Name: "{app}\InstallCount.txt"
; Not sure why this gets left behind, but it does. Clean it up...
Type: filesandordirs; Name: "{app}\locales"
Type: filesandordirs; Name: "{userappdata}\{#AppDataFolder}"
Type: filesandordirs; Name: "{localappdata}\{#AppDataFolder}"