packaging: Windows GUI installer (Inno Setup)#94
Conversation
The clicky setup.exe ex-Advantage users expect, as a thin GUI shell over the same machinery as the console wizard: it asks for data directory, wire port, Studio console and auto-start, writes openads.ini, and optionally registers the Windows service via `openads_serverd --install-service --config <ini>`. No install logic is duplicated — Linux/macOS use the console wizard directly. - packaging/windows/openads-setup.iss: Inno Setup script with custom settings/options pages, port validation, ini writer and service registration in CurStepChanged(ssPostInstall); uninstall drops the service first. Version is a build-time define (/DAppVer) so it is not hard-coded; binaries come from a staging folder (/DSrcDir). - packaging/windows/README.md: how to build it (ISCC) and what it does. Windows-only by nature; not wired into CI here. Reviewed but not compiled in this environment (no Inno Setup toolchain available) — verify with iscc on a Windows box / CI before shipping. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces a Windows installer using Inno Setup (openads-setup.iss) along with a supporting README.md to guide users through the build and installation process. The installer provides a GUI wizard to configure server settings, write the configuration file, and register the application as a Windows service. The feedback recommends defaulting the data directory to {commonappdata} instead of {autopf} to avoid write-permission issues, adding validation to prevent port conflicts, starting the service automatically post-install, and stopping the service synchronously during uninstallation to prevent file-in-use locks.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| CfgPage.Add('Studio web console port:', False); | ||
| CfgPage.Add('Studio admin user (leave blank for an open console):', False); | ||
| CfgPage.Add('Studio admin password:', True); | ||
| CfgPage.Values[0] := ExpandConstant('{autopf}\OpenADS\data'); |
There was a problem hiding this comment.
Storing dynamic database files under Program Files ({autopf}) is discouraged on Windows due to write-permission restrictions and standard directory layouts. It is highly recommended to default the data directory to {commonappdata} (which resolves to C:\ProgramData), where the service will have appropriate write permissions.
CfgPage.Values[0] := ExpandConstant('{commonappdata}\OpenADS\data');
| p := StrToIntDef(CfgPage.Values[2], -1); | ||
| if (p < 0) or (p > 65535) then | ||
| begin | ||
| MsgBox('The Studio port must be a number between 0 and 65535.', | ||
| mbError, MB_OK); | ||
| Result := False; | ||
| end; |
There was a problem hiding this comment.
Add a validation check to ensure that the wire port and the Studio port are not configured to the same value, which would cause a port binding conflict and prevent the server from starting.
p := StrToIntDef(CfgPage.Values[2], -1);
if (p < 0) or (p > 65535) then
begin
MsgBox('The Studio port must be a number between 0 and 65535.',
mbError, MB_OK);
Result := False;
Exit;
end;
if CfgPage.Values[1] = CfgPage.Values[2] then
begin
MsgBox('The wire port and the Studio port cannot be the same.',
mbError, MB_OK);
Result := False;
end;
| if ServiceWanted then | ||
| begin | ||
| if not Exec(ExpandConstant('{app}\openads_serverd.exe'), | ||
| '--install-service --config "' + iniPath + '"', | ||
| ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, rc) then | ||
| MsgBox('Could not launch the service installer.', mbError, MB_OK) | ||
| else if rc <> 0 then | ||
| MsgBox('Service registration returned code ' + IntToStr(rc) + | ||
| '. You can register it later with:'#13#10 + | ||
| ' openads_serverd --install-service --config "' + iniPath + '"', | ||
| mbInformation, MB_OK); | ||
| end; |
There was a problem hiding this comment.
After successfully registering the Windows service, it is a better user experience to start the service immediately so the user doesn't have to manually start it or reboot the system.
if ServiceWanted then
begin
if not Exec(ExpandConstant('{app}\openads_serverd.exe'),
'--install-service --config "' + iniPath + '"',
ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, rc) then
MsgBox('Could not launch the service installer.', mbError, MB_OK)
else if rc <> 0 then
MsgBox('Service registration returned code ' + IntToStr(rc) +
'. You can register it later with:'#13#10 +
' openads_serverd --install-service --config "' + iniPath + '"',
mbInformation, MB_OK)
else
begin
Exec('net.exe', 'start openads_serverd', '', SW_HIDE, ewWaitUntilTerminated, rc);
end;
end;
| [UninstallRun] | ||
| ; Drop the service (best effort) before files are removed. | ||
| Filename: "{app}\openads_serverd.exe"; Parameters: "--uninstall-service"; Flags: runhidden; RunOnceId: "DelOpenadsSvc" |
There was a problem hiding this comment.
During uninstallation, stopping the service via --uninstall-service is asynchronous and might not finish before the uninstaller attempts to delete the executable, leading to 'file in use' errors. Running net stop openads_serverd synchronously first ensures the service is fully stopped before file deletion begins.
[UninstallRun]
; Stop the service synchronously to prevent file-in-use locks, then uninstall it.
Filename: "net.exe"; Parameters: "stop openads_serverd"; Flags: runhidden; RunOnceId: "StopOpenadsSvc"
Filename: "{app}\openads_serverd.exe"; Parameters: "--uninstall-service"; Flags: runhidden; RunOnceId: "DelOpenadsSvc"
Incorporate the four review suggestions on the Inno Setup installer:
- Default the data directory under {commonappdata} (C:\ProgramData)
instead of {autopf} (Program Files): the service needs write access to
where the tables live, and Program Files is read-only / UAC-virtualised
for non-elevated processes.
- Reject a configuration where the wire port and the Studio port are the
same (the server can't bind both).
- Start the service immediately after registering it, so the user
doesn't have to reboot or start it by hand.
- On uninstall, stop the service synchronously (net stop) before
deregistering it, to avoid a file-in-use lock while deleting the .exe.
Also add README.es.md so the packaging docs are available in English and
Spanish.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The installer script from #94 did not compile with ISCC: a {autopf} constant inside a { } brace comment closed the comment early (Inno comments don't nest), and ArchitecturesInstallIn64BitMode=x64 is deprecated. Rewrote the comment as // lines and switched to x64compatible. ISCC now builds openads-<ver>-setup.exe with zero warnings/errors. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What & why
A classic Windows
setup.exe— the clicky front door ex-Advantage users expect — as a thin GUI shell over the same machinery as the console wizard (openads_serverd --setup). It asks for the data directory, wire port, Studio console and auto-start, writesopenads.ini, and optionally registers the Windows service viaopenads_serverd --install-service --config <ini>. No install logic is duplicated; Linux/macOS use the console wizard directly.packaging/windows/openads-setup.iss— Inno Setup script: custom settings/options pages, port validation, the ini writer and service registration inCurStepChanged(ssPostInstall); uninstall drops the service first. Version is a build-time define (/DAppVer) so it is not hard-coded; binaries come from a staging folder (/DSrcDir, e.g. an extracted release zip orcpackoutput).packaging/windows/README.md— how to build it (ISCC) and what it does.Pairs with the
--setupwizard (#89) and the CPack packaging (#91): point/DSrcDirat the CPack ZIP andisccwraps it into a setup.exe.Honest caveat
This is Windows-only and is not wired into CI here. I reviewed it carefully but could not compile it in my environment (no Inno Setup toolchain). Please run
isccon a Windows box / CI to verify before shipping a release.Naming
Only nominative references to Advantage/ARC for compatibility; no third-party brand claimed.