Files
Behavision/installer/behavision.iss
Suriyakumarvijayanayagam 4c62fc0ef3 The Loyaly mark everywhere a person sees the product
Brand assets in brand/ (the 512px mark, sizes for each surface, a
multi-size .ico). Windows executables carry it as a compiled-in
resource (rsrc_windows_amd64.syso from go-winres) so Explorer, the
taskbar and the installer show it; installer/build.ps1 therefore uses a
plain go build rather than wails build, which would add a second copy
and fail the link. The tray icon is the mark with a state dot over its
corner - a plain coloured circle read as a generic status light among
other icons - rendered from the embedded PNG at 32px so it survives
150% scaling. The desktop app's login, setup and sidebar marks, the
head-office web app's mark and favicon, and the engine dashboard's
favicon are the same file.

Also found while packaging: no wheel so far shipped static/, so the
engine's own dashboard at :8010 on a Windows source install would have
failed with a missing file. package-data now includes it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KGcjxF1cNLcuwc3DAPcnfj
2026-09-19 12:54:19 +05:30

165 lines
7.3 KiB
Plaintext

; Behavision installer (Inno Setup 6).
;
; Built by installer\build.ps1, which stages dist\Behavision first. Compile it
; by hand with:
; ISCC.exe /DMyAppVersion=0.1.0 installer\behavision.iss
;
; Three decisions worth reading before changing anything here:
;
; 1. ADMIN AT INSTALL TIME, NEVER AT RUN TIME. The files go under Program
; Files, so installing needs elevation. Running does not: the app is a
; normal user-session process that spawns the engine as a child, which is
; also why it can draw a tray icon at all - a Windows service runs in
; session 0 and cannot.
;
; 2. NO MODELS IN THE PACKAGE. They are ~200 MB and `setup-models` downloads
; them resumably into the state root on first run. Bundling them would
; quadruple this file and force a re-sign for a model change.
;
; 3. NOTHING WRITABLE UNDER Program Files. The database, logs, camera list,
; downloaded models and agent config all live in %PROGRAMDATA%\Behavision,
; which is what makes an upgrade a file copy rather than a migration. That
; split is behavision/paths.py and agent/pkg/paths, and this file must not
; contradict it.
#define MyAppName "Behavision"
#ifndef MyAppVersion
#define MyAppVersion "0.1.0"
#endif
#define MyAppPublisher "Loyaly"
#define MyAppURL "https://platform.loyaly.ai"
#define MyAppExeName "Behavision.exe"
[Setup]
; The Loyaly mark, on the installer and in Add/Remove Programs.
SetupIconFile=..\brand\loyaly.ico
AppId={{7C4B9E2A-3F51-4C86-9D0A-B1E7A2F65D11}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
DefaultDirName={autopf}\{#MyAppName}
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
OutputDir=..\dist
OutputBaseFilename=Behavision-Setup-{#MyAppVersion}
Compression=lzma2/max
SolidCompression=yes
WizardStyle=modern
; Admin, because Program Files is. See decision 1 above.
PrivilegesRequired=admin
ArchitecturesAllowed=x64compatible
ArchitecturesInstallIn64BitMode=x64compatible
UninstallDisplayIcon={app}\{#MyAppExeName}
; The engine folder alone is ~400 MB unpacked; saying so up front beats a
; wizard that stops halfway on a small shop PC.
ExtraDiskSpaceRequired=450000000
; Ask Windows' Restart Manager to close a running copy instead of writing DLLs
; underneath it. The engine holds the SQLite WAL and the camera, so a half
; replaced install fails on the NEXT start - long after anyone would connect
; the two events. RestartApplications=no because the [Run] section starts the
; app again itself, and twice is one process too many for one webcam.
CloseApplications=yes
RestartApplications=no
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "Create a &desktop shortcut"; GroupDescription: "Shortcuts:"
; Ticked by default: the product is meaningless if it is not watching. A shop
; PC reboots after a power cut at 3am with nobody there to open anything.
Name: "startup"; Description: "Start Behavision when this PC starts"; GroupDescription: "Startup:"
[Files]
Source: "..\dist\Behavision\Behavision.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\dist\Behavision\behavision-agent.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\dist\Behavision\engine\*"; DestDir: "{app}\engine"; Flags: ignoreversion recursesubdirs createallsubdirs
; ~2 MB bootstrapper, downloaded at build time by build.ps1. The app is a
; WebView2 window; without the runtime it opens BLANK - not an error, just an
; empty white rectangle, which is the single worst failure mode to hand a shop.
; Present on Windows 11 and recent Windows 10, absent on plenty of older
; machines, and a shop PC is exactly where an older machine lives.
Source: "vendor\MicrosoftEdgeWebview2Setup.exe"; DestDir: "{tmp}"; \
Flags: deleteafterinstall; Check: WebView2Missing
[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
; Per-user, not HKLM\Run: the app draws a tray icon and a window, so it has to
; start in an interactive session. A machine-wide entry would try before anyone
; has logged in.
Name: "{userstartup}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: startup
; Named in the installer's own text when somebody skips the download, so it has
; to exist. Console window on purpose: it is a 200 MB download with a progress
; line, and a silent one looks like nothing happened.
Name: "{group}\Download models"; Filename: "{app}\engine\behavision.exe"; \
Parameters: "setup-models"; Comment: "Download the face recognition models"
Name: "{group}\Where is my data"; Filename: "{app}\engine\behavision.exe"; \
Parameters: "paths"; Comment: "Print the installed layout"
[Dirs]
; Created here so a first run does not have to, and ACLed to Administrators
; plus the installing user rather than Everyone: it holds face templates, which
; are biometric personal data, and the engine's generated API password.
Name: "{commonappdata}\Behavision"; Permissions: admins-full users-modify
[Run]
Filename: "{tmp}\MicrosoftEdgeWebview2Setup.exe"; Parameters: "/silent /install"; \
StatusMsg: "Installing Microsoft Edge WebView2 (required to show the app)..."; \
Flags: waituntilterminated; Check: WebView2Missing
; ~200 MB over the network, so it is offered rather than forced, and it is
; resumable: a killed download leaves a .part file and the next run continues.
Filename: "{app}\engine\behavision.exe"; Parameters: "setup-models"; \
StatusMsg: "Downloading face recognition models (about 200 MB)..."; \
Flags: runhidden waituntilterminated; Check: WantModels
Filename: "{app}\{#MyAppExeName}"; Description: "Start {#MyAppName} now"; \
Flags: nowait postinstall skipifsilent
[UninstallDelete]
; The unpacked engine writes nothing here, but PyInstaller leaves stray
; __pycache__ directories that would keep {app} alive after an uninstall.
Type: filesandordirs; Name: "{app}\engine"
[Code]
var
ModelsPage: TInputOptionWizardPage;
procedure InitializeWizard;
begin
ModelsPage := CreateInputOptionPage(wpSelectTasks,
'Face recognition models',
'Behavision needs about 200 MB of model files to recognise faces.',
'These are downloaded once. If this PC has no internet connection now, ' +
'skip this and run "Download models" from the Start menu later - the app ' +
'will not recognise anyone until they are present.',
True, False);
ModelsPage.Add('Download the models now (recommended)');
ModelsPage.Values[0] := True;
end;
function WantModels: Boolean;
begin
Result := ModelsPage.Values[0];
end;
// The WebView2 runtime registers itself under EdgeUpdate with a non-empty
// version. Checked in three places because the runtime can be installed
// per-machine (both registry views on 64-bit) or per-user.
function WebView2Missing: Boolean;
const
CLIENT = '{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}';
var
pv: string;
begin
Result := True;
if RegQueryStringValue(HKLM, 'SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\' + CLIENT, 'pv', pv) and (pv <> '') then
Result := False
else if RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\EdgeUpdate\Clients\' + CLIENT, 'pv', pv) and (pv <> '') then
Result := False
else if RegQueryStringValue(HKCU, 'SOFTWARE\Microsoft\EdgeUpdate\Clients\' + CLIENT, 'pv', pv) and (pv <> '') then
Result := False;
end;