66#define MyAppPublisher " Nova Foundry"
77#define MyAppURL " novafoundry.ca/wormhole"
88#define MyAppExeName " wormhole.exe"
9-
109[Setup]
1110; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
1211; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
@@ -30,44 +29,38 @@ ArchitecturesAllowed=x64compatible
3029ArchitecturesInstallIn64BitMode = x64compatible
3130DisableProgramGroupPage = yes
3231LicenseFile = C:\Users\jackp\Downloads\Wormhole\LICENSE.txt
33-
3432; *** MODIFICATION: Chocolatey requires Admin rights ***
3533PrivilegesRequired = admin
3634PrivilegesRequiredOverridesAllowed= dialog
37-
3835OutputDir = C:\Users\jackp\Downloads
3936OutputBaseFilename = Wormhole_setup
4037SetupIconFile = C:\Users\jackp\Downloads\Installer Icon template.ico
4138SolidCompression = yes
4239WizardStyle = modern dynamic
43-
4440[Languages]
4541Name : " english" ; MessagesFile : " compiler:Default.isl"
46-
4742[Tasks]
4843Name : " desktopicon" ; Description : " {cm:CreateDesktopIcon}" ; GroupDescription: " {cm:AdditionalIcons}" ; Flags : unchecked
49-
44+ Name : " forcepandoc" ; Description : " Force reinstall Pandoc (even if already detected)" ; GroupDescription: " {cm:AdditionalIcons}" ; Flags : unchecked
45+ Name : " forcechoco" ; Description : " Force reinstall Chocolatey (even if already detected)" ; GroupDescription: " {cm:AdditionalIcons}" ; Flags : unchecked
46+ Name : " forceffmpeg" ; Description : " Force reinstall FFmpeg (even if already detected)" ; GroupDescription: " {cm:AdditionalIcons}" ; Flags : unchecked
47+ Name : " showdetails" ; Description : " Show terminal windows for dependency installations" ; GroupDescription: " {cm:AdditionalIcons}" ; Flags : unchecked
5048[Files]
5149Source : " C:\Users\jackp\Downloads\Wormhole\{#MyAppExeName}" ; DestDir : " {app} " ; Flags : ignoreversion
5250Source : " C:\Users\jackp\Downloads\Wormhole\*" ; DestDir : " {app} " ; Flags : ignoreversion recursesubdirs createallsubdirs
5351; NOTE: Don't use "Flags: ignoreversion" on any shared system files
54-
5552[Icons]
5653Name : " {autoprograms}\{#MyAppName}" ; Filename : " {app} \{#MyAppExeName}"
5754Name : " {autodesktop}\{#MyAppName}" ; Filename : " {app} \{#MyAppExeName}" ; Tasks: desktopicon
58-
5955[Run]
6056Filename : " {app} \{#MyAppExeName}" ; Parameters : " --register" ; Description : " Register context menu" ; Flags : runhidden
6157Filename : " {app} \{#MyAppExeName}" ; Description : " {cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}" ; Flags : nowait postinstall skipifsilent runascurrentuser
62-
6358[UninstallRun]
6459Filename : " {app} \{#MyAppExeName}" ; Parameters : " --unregister" ; RunOnceId: " UnregisterContextMenu" ; Flags : runhidden
65-
6660[Code]
6761var
6862 InstalledPandoc: Boolean;
6963 InstalledFFmpeg: Boolean;
70-
7164// Function to handle Pandoc installation
7265function InstallPandoc (): String;
7366var
7669 LogPath: String;
7770 DownloadScript: String;
7871 PandocExePath: String;
72+ ShowDetails: Boolean;
7973begin
8074 InstalledPandoc := False;
81- // 1. Check if Pandoc is already installed via PATH
82- if Exec(ExpandConstant(' {cmd}' ), ' /C pandoc --version' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0 ) then
75+ ShowDetails := IsTaskSelected(' showdetails' );
76+ // 1. Check if Pandoc is already installed via PATH, unless force
77+ if (not IsTaskSelected(' forcepandoc' )) and Exec(ExpandConstant(' {cmd}' ), ' /C pandoc --version' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0 ) then
8378 begin
8479 Result := ' ' ; // Already installed, success
8580 Exit;
8681 end ;
87-
82+
8883 // 2. Download the latest Pandoc MSI using PowerShell
8984 PandocMsiPath := ExpandConstant(' {tmp}\pandoc-latest-windows-x86_64.msi' );
9085 LogPath := ExpandConstant(' {tmp}\pandoc_download.log' );
91-
86+
9287 // PowerShell script to fetch latest release and download MSI
93- DownloadScript :=
94- ' $ProgressPreference = '' SilentlyContinue'' ; ' +
88+ DownloadScript :=
89+ ' $ProgressPreference = '' SilentlyContinue'' ; ' +
9590 ' try { ' +
96- ' $latest = (Invoke-WebRequest -Uri https://api.github.com/repos/jgm/pandoc/releases/latest -UseBasicParsing).Content | ConvertFrom-Json; ' +
97- ' $asset = $latest.assets | Where-Object { $_.name -like '' pandoc-*-windows-x86_64.msi'' }; ' +
98- ' if ($asset -eq $null) { throw '' MSI asset not found in latest release.'' ; } ' +
99- ' $downloadUrl = $asset.browser_download_url; ' +
100- ' Invoke-WebRequest -Uri $downloadUrl -OutFile '' ' + PandocMsiPath + ' '' ; ' +
91+ ' $latest = (Invoke-WebRequest -Uri https://api.github.com/repos/jgm/pandoc/releases/latest -UseBasicParsing).Content | ConvertFrom-Json; ' +
92+ ' $asset = $latest.assets | Where-Object { $_.name -like '' pandoc-*-windows-x86_64.msi'' }; ' +
93+ ' if ($asset -eq $null) { throw '' MSI asset not found in latest release.'' ; } ' +
94+ ' $downloadUrl = $asset.browser_download_url; ' +
95+ ' Invoke-WebRequest -Uri $downloadUrl -OutFile '' ' + PandocMsiPath + ' '' ; ' +
10196 ' } catch { ' +
102- ' $_.Exception.Message | Out-File -FilePath '' ' + LogPath + ' '' ; ' +
103- ' exit 1; ' +
97+ ' $_.Exception.Message | Out-File -FilePath '' ' + LogPath + ' '' ; ' +
98+ ' exit 1; ' +
10499 ' }' ;
105-
100+
106101 WizardForm.StatusLabel.Caption := ' Downloading latest Pandoc MSI (this may take a moment)...' ;
107102 WizardForm.ProgressGauge.Style := npbstMarquee;
108103 try
@@ -120,27 +115,38 @@ begin
120115 WizardForm.ProgressGauge.Style := npbstNormal;
121116 WizardForm.StatusLabel.Caption := ' ' ;
122117 end ;
123-
118+
124119 // Check if the MSI file was downloaded
125120 if not FileExists(PandocMsiPath) then
126121 begin
127122 Result := ' Pandoc MSI download failed or file not found.' ;
128123 Exit;
129124 end ;
130-
125+
131126 // 3. Install the downloaded MSI (silent, hidden, for all users) with logging
132127 LogPath := ExpandConstant(' {tmp}\pandoc_install.log' ); // Reuse for install log
133- if not Exec( ' msiexec.exe ' , ' /i " ' + PandocMsiPath + ' " ALLUSERS=1 /qn /norestart /L*V " ' + LogPath + ' " ' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) then
128+ if ShowDetails then
134129 begin
135- Result := ' Failed to execute msiexec for Pandoc. Code: ' + IntToStr(ResultCode) + ' . Check log at ' + LogPath;
136- Exit;
130+ if not Exec(' msiexec.exe' , ' /i "' + PandocMsiPath + ' " ALLUSERS=1 /qb /norestart /L*V "' + LogPath + ' "' , ' ' , SW_SHOW, ewWaitUntilTerminated, ResultCode) then
131+ begin
132+ Result := ' Failed to execute msiexec for Pandoc. Code: ' + IntToStr(ResultCode) + ' . Check log at ' + LogPath;
133+ Exit;
134+ end ;
135+ end
136+ else
137+ begin
138+ if not Exec(' msiexec.exe' , ' /i "' + PandocMsiPath + ' " ALLUSERS=1 /qn /norestart /L*V "' + LogPath + ' "' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) then
139+ begin
140+ Result := ' Failed to execute msiexec for Pandoc. Code: ' + IntToStr(ResultCode) + ' . Check log at ' + LogPath;
141+ Exit;
142+ end ;
137143 end ;
138144 if ResultCode <> 0 then
139145 begin
140146 Result := ' Pandoc installation failed. Code: ' + IntToStr(ResultCode) + ' . Check log at ' + LogPath;
141147 Exit;
142148 end ;
143-
149+
144150 // 4. Verify installation using full path (since PATH may not update yet)
145151 PandocExePath := ExpandConstant(' {commonpf}\Pandoc\pandoc.exe' );
146152 if not FileExists(PandocExePath) then
@@ -156,133 +162,174 @@ begin
156162 end ;
157163 end ;
158164 end ;
159-
165+
160166 if not Exec(PandocExePath, ' --version' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) or (ResultCode <> 0 ) then
161167 begin
162168 Result := ' Pandoc installed but --version failed even with full path. Code: ' + IntToStr(ResultCode);
163169 Exit;
164170 end ;
165-
171+
166172 InstalledPandoc := True; // Flag for restart
167173 Result := ' ' ; // Success
168174end ;
169-
170175// *** NEW FUNCTION: Helper to install Chocolatey ***
171176function InstallChocolatey (): String;
172177var
173178 ResultCode: Integer;
174179 ChocoInstallScript: String;
180+ LogPath: String;
181+ ShowDetails: Boolean;
175182begin
183+ ShowDetails := IsTaskSelected(' showdetails' );
184+ LogPath := ExpandConstant(' {tmp}\choco_install.log' );
176185 WizardForm.StatusLabel.Caption := ' Installing Chocolatey package manager...' ;
177-
178- // Official Chocolatey install command
179- ChocoInstallScript := ' Set-ExecutionPolicy Bypass -Scope Process -Force; ' +
180- ' [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; ' +
181- ' iex ((New-Object System.Net.WebClient).DownloadString('' https://community.chocolatey.org/install.ps1'' ))' ;
182-
183- // Run PowerShell with SW_SHOW to show the terminal to the user
184- if not Exec(' powershell.exe' , ' -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "' + ChocoInstallScript + ' "' , ' ' , SW_SHOW, ewWaitUntilTerminated, ResultCode) then
186+
187+ // Official Chocolatey install command with try-catch and logging
188+ ChocoInstallScript :=
189+ ' $ProgressPreference = '' SilentlyContinue'' ; ' +
190+ ' try { ' +
191+ ' Set-ExecutionPolicy Bypass -Scope Process -Force; ' +
192+ ' [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; ' +
193+ ' iex ((New-Object System.Net.WebClient).DownloadString('' https://community.chocolatey.org/install.ps1'' )); ' +
194+ ' } catch { ' +
195+ ' $_.Exception.Message | Out-File -FilePath '' ' + LogPath + ' '' ; ' +
196+ ' exit 1; ' +
197+ ' }' ;
198+ // Run PowerShell, show window if showdetails
199+ if ShowDetails then
185200 begin
186- Result := ' Failed to launch PowerShell for Chocolatey installation. Code: ' + IntToStr(ResultCode);
187- Exit;
201+ if not Exec(' powershell.exe' , ' -NoProfile -ExecutionPolicy Bypass -Command "' + ChocoInstallScript + ' "' , ' ' , SW_SHOW, ewWaitUntilTerminated, ResultCode) then
202+ begin
203+ Result := ' Failed to launch PowerShell for Chocolatey installation. Code: ' + IntToStr(ResultCode);
204+ Exit;
205+ end ;
206+ end
207+ else
208+ begin
209+ if not Exec(' powershell.exe' , ' -NoProfile -ExecutionPolicy Bypass -Command "' + ChocoInstallScript + ' " > "' + LogPath + ' " 2>&1' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) then
210+ begin
211+ Result := ' Failed to launch PowerShell for Chocolatey installation. Code: ' + IntToStr(ResultCode);
212+ Exit;
213+ end ;
188214 end ;
189-
190215 if ResultCode <> 0 then
191216 begin
192- Result := ' Chocolatey installation failed. Code: ' + IntToStr(ResultCode);
217+ Result := ' Chocolatey installation failed. Code: ' + IntToStr(ResultCode) + ' . Check log at ' + LogPath + ' for details. ' ;
193218 Exit;
194219 end ;
195-
196220 Result := ' ' ;
197221end ;
198-
199222// Function to handle FFmpeg installation
200223function InstallFFmpeg (): String;
201224var
202225 ResultCode: Integer;
203226 FFmpegExePath: String;
204227 ChocoExePath: String;
205228 ChocoInstallResult: String;
229+ LogPath: String;
230+ ShowDetails: Boolean;
206231begin
207232 InstalledFFmpeg := False;
208-
209- // 1. Check if FFmpeg is already installed via PATH
210- if Exec(ExpandConstant(' {cmd}' ), ' /C ffmpeg -version' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0 ) then
233+ LogPath := ExpandConstant(' {tmp}\ffmpeg_install.log' );
234+ ShowDetails := IsTaskSelected(' showdetails' );
235+
236+ // 1. Check if FFmpeg is already installed via PATH, unless force
237+ if (not IsTaskSelected(' forceffmpeg' )) and Exec(ExpandConstant(' {cmd}' ), ' /C ffmpeg -version' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0 ) then
211238 begin
212239 Result := ' ' ; // Already installed, success
213240 Exit;
214241 end ;
215-
242+
216243 // 2. Check if Chocolatey is installed
217244 if not Exec(ExpandConstant(' {cmd}' ), ' /C choco -v' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) or (ResultCode <> 0 ) then
218245 begin
219246 // *** MODIFICATION: Install Chocolatey if missing ***
220247 ChocoInstallResult := InstallChocolatey();
221-
248+
222249 if ChocoInstallResult <> ' ' then
223250 begin
224251 // If Chocolatey failed to install, we can't proceed with FFmpeg
225252 Result := ChocoInstallResult;
226253 Exit;
227254 end ;
228255 end ;
229-
256+
230257 // 3. Choco is installed (or was just installed), install FFmpeg.
231258 WizardForm.StatusLabel.Caption := ' Installing FFmpeg via Chocolatey (this may take a few minutes)...' ;
232259 WizardForm.ProgressGauge.Style := npbstMarquee;
233-
260+
234261 try
235262 // Determine path to choco. If we just installed it, it might not be in PATH yet for the installer process.
236263 // Try the standard install location first.
237264 ChocoExePath := ' C:\ProgramData\chocolatey\bin\choco.exe' ;
238-
265+
239266 if FileExists(ChocoExePath) then
240267 begin
241268 // Use absolute path
242- if not Exec(ChocoExePath, ' install ffmpeg -y ' , ' ' , SW_SHOW, ewWaitUntilTerminated, ResultCode) then
269+ if ShowDetails then
243270 begin
244- Result := ' Failed to launch Chocolatey (Absolute Path) to install FFmpeg. Code: ' + IntToStr(ResultCode);
245- Exit;
271+ if not Exec(ChocoExePath, ' install ffmpeg -y' , ' ' , SW_SHOW, ewWaitUntilTerminated, ResultCode) then
272+ begin
273+ Result := ' Failed to launch Chocolatey (Absolute Path) to install FFmpeg. Code: ' + IntToStr(ResultCode);
274+ Exit;
275+ end ;
276+ end
277+ else
278+ begin
279+ if not Exec(ExpandConstant(' {cmd}' ), ' /C "' + ChocoExePath + ' " install ffmpeg -y > "' + LogPath + ' " 2>&1' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) then
280+ begin
281+ Result := ' Failed to launch Chocolatey (Absolute Path) to install FFmpeg. Code: ' + IntToStr(ResultCode);
282+ Exit;
283+ end ;
246284 end ;
247285 end
248286 else
249287 begin
250288 // Fallback to global PATH
251- if not Exec(ExpandConstant(' {cmd}' ), ' /C choco install ffmpeg -y' , ' ' , SW_SHOW, ewWaitUntilTerminated, ResultCode) then
289+ if ShowDetails then
290+ begin
291+ if not Exec(' choco.exe' , ' install ffmpeg -y' , ' ' , SW_SHOW, ewWaitUntilTerminated, ResultCode) then
292+ begin
293+ Result := ' Failed to launch Chocolatey (Global PATH) to install FFmpeg. Code: ' + IntToStr(ResultCode);
294+ Exit;
295+ end ;
296+ end
297+ else
252298 begin
253- Result := ' Failed to launch Chocolatey (Global PATH) to install FFmpeg. Code: ' + IntToStr(ResultCode);
254- Exit;
299+ if not Exec(ExpandConstant(' {cmd}' ), ' /C choco install ffmpeg -y > "' + LogPath + ' " 2>&1' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) then
300+ begin
301+ Result := ' Failed to launch Chocolatey (Global PATH) to install FFmpeg. Code: ' + IntToStr(ResultCode);
302+ Exit;
303+ end ;
255304 end ;
256305 end ;
257-
258306 if ResultCode <> 0 then
259307 begin
260- Result := ' Chocolatey failed to install FFmpeg. Code: ' + IntToStr(ResultCode);
308+ Result := ' Chocolatey failed to install FFmpeg. Code: ' + IntToStr(ResultCode) + ' . Check log at ' + LogPath + ' for details. ' ;
261309 Exit;
262310 end ;
263311 finally
264312 WizardForm.ProgressGauge.Style := npbstNormal;
265313 WizardForm.StatusLabel.Caption := ' ' ;
266314 end ;
267-
315+
268316 // 4. Verify installation using full path
269317 FFmpegExePath := ' C:\ProgramData\chocolatey\bin\ffmpeg.exe' ;
270318 if not FileExists(FFmpegExePath) then
271319 begin
272320 Result := ' FFmpeg installed but executable not found in expected path.' ;
273321 Exit;
274322 end ;
275-
323+
276324 if not Exec(FFmpegExePath, ' -version' , ' ' , SW_HIDE, ewWaitUntilTerminated, ResultCode) or (ResultCode <> 0 ) then
277325 begin
278326 Result := ' FFmpeg installed but -version failed even with full path. Code: ' + IntToStr(ResultCode);
279327 Exit;
280328 end ;
281-
329+
282330 InstalledFFmpeg := True; // Flag for restart
283331 Result := ' ' ; // Success
284332end ;
285-
286333// Main function called by Setup
287334function PrepareToInstall (var NeedsRestart: Boolean): String;
288335var
@@ -291,26 +338,26 @@ var
291338begin
292339 InstalledPandoc := False;
293340 InstalledFFmpeg := False;
294-
341+
295342 // First, check/install Pandoc
296343 PandocResult := InstallPandoc();
297344 if PandocResult <> ' ' then
298345 begin
299346 Result := PandocResult; // Return Pandoc error
300347 Exit;
301348 end ;
302-
349+
303350 // Second, check/install FFmpeg (and Choco if needed)
304351 FFmpegResult := InstallFFmpeg();
305352 if FFmpegResult <> ' ' then
306353 begin
307354 Result := FFmpegResult; // Return FFmpeg error
308355 Exit;
309356 end ;
310-
357+
311358 // If either was freshly installed, request restart for PATH updates
312359 if InstalledPandoc or InstalledFFmpeg then
313360 NeedsRestart := True;
314-
361+
315362 Result := ' ' ; // All good, both are installed
316363end ;
0 commit comments