; studioE5 Agent Installer (Inno Setup) ; Build with Inno Setup Compiler (ISCC) on Windows. ; This installer bundles the agent and Tailscale binaries. It checks ; prerequisites and guides the user through installing missing system ; components (WSL2 + Podman) before installing studioE5. #define MyAppName "studioE5 Agent" #define MyAppVersion "0.3.17" #define MyAppPublisher "studioE5" #define MyAppURL "https://studioe5.edudeploy.com" #define MyAppExeName "studioE5-agent.exe" [Setup] AppId={{studioE5-agent-ondemand} AppName={#MyAppName} AppVersion={#MyAppVersion} AppPublisher={#MyAppPublisher} AppPublisherURL={#MyAppURL} AppSupportURL={#MyAppURL} AppUpdatesURL={#MyAppURL} DefaultDirName={autopf}\studioE5-agent DisableProgramGroupPage=yes OutputDir=..\..\installer-output OutputBaseFilename=studioE5-agent-{#MyAppVersion}-setup Compression=lzma SolidCompression=yes WizardStyle=modern PrivilegesRequired=admin ArchitecturesAllowed=x64 ArchitecturesInstallIn64BitMode=x64 [Languages] Name: "french"; MessagesFile: "compiler:Languages\French.isl" [Tasks] Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked [Files] Source: "..\..\agent\studioE5-agent.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "..\..\agent\tailscale-bin\windows\tailscale.exe"; DestDir: "{app}\tailscale-bin\windows"; Flags: ignoreversion Source: "..\..\agent\tailscale-bin\windows\tailscaled.exe"; DestDir: "{app}\tailscale-bin\windows"; Flags: ignoreversion Source: "..\..\agent\tailscale-bin\windows\wintun.dll"; DestDir: "{app}\tailscale-bin\windows"; Flags: ignoreversion Source: "..\..\README.md"; DestDir: "{app}"; Flags: ignoreversion [Icons] Name: "{autoprograms}\studioE5 Agent"; Filename: "{app}\{#MyAppExeName}" Name: "{autodesktop}\studioE5 Agent"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon [Run] Filename: "{app}\{#MyAppExeName}"; Description: "Lancer studioE5 Agent"; Flags: nowait postinstall skipifsilent [UninstallRun] Filename: "{cmd}"; Parameters: "/c taskkill /f /im studioE5-agent.exe"; Flags: runhidden waituntilterminated [Code] var PrereqPage: TWizardPage; lblStatus: TLabel; btnCheck: TButton; function GetPhysicallyInstalledSystemMemoryKB(var TotalMemoryInKilobytes: Int64): Boolean; external 'GetPhysicallyInstalledSystemMemory@kernel32.dll stdcall'; function GetTotalPhysicalMemoryMB(): Cardinal; var MemKB: Int64; begin if GetPhysicallyInstalledSystemMemoryKB(MemKB) then Result := Cardinal(MemKB div 1024) else Result := 0; end; function IsWSL2Installed(): Boolean; var ResultCode: Integer; begin Result := Exec('wsl.exe', '--version', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0); end; function IsPodmanReady(): Boolean; var ResultCode: Integer; begin Result := Exec('podman.exe', 'machine list', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0); end; function GetDiskFreeSpaceEx( lpDirectoryName: string; var lpFreeBytesAvailableToCaller: Int64; var lpTotalNumberOfBytes: Int64; var lpTotalNumberOfFreeBytes: Int64 ): Boolean; external 'GetDiskFreeSpaceExW@kernel32.dll stdcall'; function GetFreeDiskSpaceMB(const Path: string): Cardinal; var FreeBytes, TotalBytes: Int64; Dummy: Int64; begin if GetDiskFreeSpaceEx(Path, FreeBytes, TotalBytes, Dummy) then Result := Cardinal(FreeBytes div (1024 * 1024)) else Result := 0; end; procedure UpdatePrereqStatus(); var Msg: string; RamMB, FreeMB: Cardinal; WSLReady, PodmanReady: Boolean; begin RamMB := GetTotalPhysicalMemoryMB(); FreeMB := GetFreeDiskSpaceMB('C:\'); WSLReady := IsWSL2Installed(); PodmanReady := IsPodmanReady(); Msg := 'Vérification des prérequis :' + #13#10#13#10; if RamMB >= 8192 then Msg := Msg + '✅ Mémoire vive (RAM) : ' + IntToStr(RamMB div 1024) + ' Go' + #13#10 else Msg := Msg + '⚠️ Mémoire vive (RAM) : ' + IntToStr(RamMB div 1024) + ' Go (8 Go recommandés)' + #13#10; if FreeMB >= 10240 then Msg := Msg + '✅ Espace disque disponible : ' + IntToStr(FreeMB div 1024) + ' Go' + #13#10 else Msg := Msg + '⚠️ Espace disque disponible : ' + IntToStr(FreeMB div 1024) + ' Go (10 Go recommandés)' + #13#10; if WSLReady then Msg := Msg + '✅ Environnement de virtualisation (WSL2) installé' + #13#10 else Msg := Msg + '❌ Environnement de virtualisation (WSL2) non installé' + #13#10; if PodmanReady then Msg := Msg + '✅ Service de conteneurs (Podman) prêt' + #13#10 else Msg := Msg + '❌ Service de conteneurs (Podman) non prêt' + #13#10; Msg := Msg + #13#10; if WSLReady and PodmanReady and (RamMB >= 4096) and (FreeMB >= 5120) then Msg := Msg + 'Tous les prérequis sont satisfaits. Vous pouvez installer studioE5 Agent.' else begin Msg := Msg + 'Ordre d''installation recommandé :' + #13#10; if not WSLReady then Msg := Msg + '1. Installer WSL2 : ouvrir PowerShell en administrateur et exécuter : wsl --install --no-distribution' + #13#10; if not PodmanReady then Msg := Msg + '2. Installer Podman : télécharger et exécuter le MSI depuis https://github.com/containers/podman/releases' + #13#10; if not PodmanReady then Msg := Msg + '3. Initialiser Podman : podman machine init && podman machine start' + #13#10; Msg := Msg + #13#10 + 'Après avoir installé les éléments manquants, relancez cet installateur.'; end; lblStatus.Caption := Msg; end; procedure btnCheckClick(Sender: TObject); begin UpdatePrereqStatus(); end; procedure InitializeWizard(); begin PrereqPage := CreateCustomPage(wpWelcome, 'Vérification des prérequis', 'Assurez-vous que votre poste est prêt avant d''installer studioE5 Agent.'); lblStatus := TLabel.Create(WizardForm); lblStatus.Parent := PrereqPage.Surface; lblStatus.Left := 0; lblStatus.Top := 0; lblStatus.Width := PrereqPage.SurfaceWidth; lblStatus.Height := 220; lblStatus.AutoSize := False; lblStatus.WordWrap := True; btnCheck := TButton.Create(WizardForm); btnCheck.Parent := PrereqPage.Surface; btnCheck.Left := 0; btnCheck.Top := lblStatus.Top + lblStatus.Height + 12; btnCheck.Width := 160; btnCheck.Height := 25; btnCheck.Caption := 'Vérifier les prérequis'; btnCheck.OnClick := @btnCheckClick; UpdatePrereqStatus(); end; function NextButtonClick(CurPageID: Integer): Boolean; begin Result := True; if CurPageID = PrereqPage.ID then begin if not (IsWSL2Installed() and IsPodmanReady()) then begin MsgBox('Certains prérequis sont manquants. Veuillez les installer avant de continuer.', mbError, MB_OK); Result := False; end; end; end;