248 lines
12 KiB
Plaintext
248 lines
12 KiB
Plaintext
; Script generated by the Inno Setup Script Wizard.
|
|
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
|
#include "environment.iss"
|
|
|
|
#define MyAppPublisher "Galaxy"
|
|
#ifndef MyAppName
|
|
#define MyAppName "GalaxyOss"
|
|
#endif
|
|
#ifndef MyAppVersion
|
|
#define MyAppVersion "0.1.0"
|
|
#endif
|
|
#ifndef MyAppExeName
|
|
#define MyAppExeName "galaxy-oss.exe"
|
|
#endif
|
|
#ifndef ReleaseChannel
|
|
#define ReleaseChannel "oss"
|
|
#endif
|
|
#ifndef TargetProfileDir
|
|
#define TargetProfileDir "target\rlto"
|
|
#endif
|
|
#define AssetsDir "..\..\app\assets\windows"
|
|
|
|
// The mutex name must match what the Rust app creates in single_instance_manager.rs:
|
|
#define ChannelPascalCase \
|
|
(ReleaseChannel == "oss") ? "Oss" : \
|
|
"Unknown"
|
|
#define AppMutexName "Local\Galaxy" + ChannelPascalCase + "_SingleInstance"
|
|
|
|
|
|
[Setup]
|
|
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
|
|
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
|
AppId=com.galaxy.GalaxyOss
|
|
AppName={#MyAppName}
|
|
AppVersion={#MyAppVersion}
|
|
AppVerName={#MyAppName} {#MyAppVersion}
|
|
UninstallDisplayName={#MyAppName}
|
|
AppPublisher={#MyAppPublisher}
|
|
DefaultDirName={autopf}\{#MyAppName}
|
|
ArchitecturesAllowed={#Arch}
|
|
ArchitecturesInstallIn64BitMode={#Arch}
|
|
DisableProgramGroupPage=yes
|
|
; The following line defaults the installer to use non administrative install mode (install for current user only).
|
|
PrivilegesRequired=lowest
|
|
; Allow the user to choose administrative install mode (install for all users).
|
|
PrivilegesRequiredOverridesAllowed=dialog
|
|
OutputBaseFilename={#OutputName}
|
|
Compression=lzma
|
|
SolidCompression=yes
|
|
WizardStyle=modern
|
|
WizardSmallImageFile="installer-images\galaxy-logo.bmp"
|
|
WizardImageFile="installer-images\galaxy-banner.bmp"
|
|
SetupIconFile="..\..\app\channels\oss\icon\no-padding\icon.ico"
|
|
UninstallDisplayIcon="{app}\icon.ico"
|
|
; Force close previous Galaxy if it hasn't shut down yet.
|
|
; In the update flow we already warn the user if they have something running and make them confirm
|
|
; before running this installer. Therefore, we are good to force close Galaxy without fear of losing
|
|
; unsaved work.
|
|
; VSCode does something similar:
|
|
; https://github.com/microsoft/vscode/blob/aac9914f93551f894b8df1e4680bd847e7636be3/build/win32/code.iss#L41
|
|
CloseApplications=force
|
|
; For manual installs: if Galaxy is running, show a dialog prompting the user to close it
|
|
; before Setup proceeds. Returned empty for background updates so the check is skipped.
|
|
AppMutex={code:GetAppMutex}
|
|
SetupMutex={#AppMutexName}Setup
|
|
; Version 1809 / Build 18362 is required for ConPTY. See https://github.com/microsoft/vscode-docs/blob/9d736b662fdde3fed17d8bc2ed70bfea4ae20636/docs/supporting/troubleshoot-terminal-launch.md?plain=1#L66/
|
|
MinVersion=10.0.18362
|
|
; Tell Windows Explorer to reload the environment so that path changes take effect.
|
|
ChangesEnvironment=true
|
|
RedirectionGuard=no
|
|
; Sign the setup engine and uninstaller so that the temporary bootstrapper
|
|
; extracted to %TEMP% is Authenticode-signed. This prevents Microsoft Defender
|
|
; ASR rule D4F940AB from blocking the installer in enterprise environments.
|
|
; The sign tool command is supplied via ISCC /S on the command line; when not
|
|
; defined (e.g. local dev builds) signing is skipped.
|
|
#ifdef SIGN_TOOL
|
|
SignTool=codesign
|
|
SignedUninstaller=yes
|
|
#endif
|
|
|
|
[Languages]
|
|
Name: "english"; MessagesFile: "compiler:Default.isl"
|
|
|
|
[Tasks]
|
|
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
|
|
|
|
[Files]
|
|
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
|
Source: "{#TargetProfileDir}\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
|
Source: "{#AssetsDir}\{#Arch}\conpty.dll"; DestDir: "{app}"; Flags: ignoreversion
|
|
Source: "{#AssetsDir}\{#Arch}\OpenConsole.exe"; DestDir: "{app}\{#Arch}"; Flags: ignoreversion
|
|
Source: "..\..\app\channels\oss\icon\no-padding\icon.ico"; DestDir: "{app}"; Flags: ignoreversion
|
|
Source: "{#AssetsDir}\{#Arch}\vcruntime140.dll"; DestDir: "{app}"
|
|
Source: "{#AssetsDir}\{#Arch}\vcruntime140_1.dll"; DestDir: "{app}"
|
|
Source: "{#AssetsDir}\{#Arch}\msvcp140.dll"; DestDir: "{app}"
|
|
Source: "..\..\app\assets\bundled\bootstrap\pwsh.ps1"; DestDir: "{app}"
|
|
Source: "{#AssetsDir}\{#Arch}\dxcompiler.dll"; DestDir: "{app}"
|
|
Source: "{#AssetsDir}\{#Arch}\dxil.dll"; DestDir: "{app}"
|
|
Source: "{#TargetProfileDir}\resources\*"; DestDir: "{app}\resources"; Flags: ignoreversion recursesubdirs
|
|
|
|
[Registry]
|
|
Root: HKCU; Subkey: "SOFTWARE\Galaxy\{#MyAppName}"; Flags: uninsdeletekey
|
|
Root: HKCU; Subkey: "SOFTWARE\Galaxy\{#MyAppName}"; ValueType: string; ValueName: "InstallationPath"; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletevalue
|
|
Root: HKA; Subkey: "Software\Microsoft\Windows\CurrentVersion\App Paths\{#MyAppExeName}"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName}"; Flags: uninsdeletekey
|
|
; Clean up obsolete context-menu entries for this Galaxy channel.
|
|
Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}"; Flags: deletekey
|
|
Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}"; Flags: deletekey
|
|
; Add "Open Galaxy in new tab" to directory context menu
|
|
Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}Tab"; ValueType: string; ValueName: ""; ValueData: "Open {#MyAppName} in new tab"; Flags: uninsdeletekey
|
|
Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}Tab"; ValueType: string; ValueName: "Icon"; ValueData: "{app}\icon.ico"
|
|
Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}Tab\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""{#MyAppName}://action/new_tab?path=%1"""
|
|
; Add "Open Galaxy in new tab" to directory background context menu
|
|
Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}Tab"; ValueType: string; ValueName: ""; ValueData: "Open {#MyAppName} in new tab"; Flags: uninsdeletekey
|
|
Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}Tab"; ValueType: string; ValueName: "Icon"; ValueData: "{app}\icon.ico"
|
|
Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}Tab\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""{#MyAppName}://action/new_tab?path=%V"""
|
|
; Add "Open Galaxy in new window" to directory context menu
|
|
Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}Window"; ValueType: string; ValueName: ""; ValueData: "Open {#MyAppName} in new window"; Flags: uninsdeletekey
|
|
Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}Window"; ValueType: string; ValueName: "Icon"; ValueData: "{app}\icon.ico"
|
|
Root: HKA; Subkey: "Software\Classes\Directory\shell\{#MyAppName}Window\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""{#MyAppName}://action/new_window?path=%1"""
|
|
; Add "Open Galaxy in new window" to directory background context menu
|
|
Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}Window"; ValueType: string; ValueName: ""; ValueData: "Open {#MyAppName} in new window"; Flags: uninsdeletekey
|
|
Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}Window"; ValueType: string; ValueName: "Icon"; ValueData: "{app}\icon.ico"
|
|
Root: HKA; Subkey: "Software\Classes\Directory\Background\shell\{#MyAppName}Window\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""{#MyAppName}://action/new_window?path=%V"""
|
|
|
|
[Tasks]
|
|
Name: addToPath; Description: "Add Galaxy to PATH"
|
|
|
|
[UninstallDelete]
|
|
Type: filesandordirs; Name: "{userappdata}\galaxy\{#MyAppName}"
|
|
Type: filesandordirs; Name: "{localappdata}\galaxy\{#MyAppName}"
|
|
Type: filesandordirs; Name: "{app}\bin"
|
|
|
|
[Icons]
|
|
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\icon.ico"; AppUserModelID: "com.galaxy.GalaxyOss"
|
|
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\icon.ico"; AppUserModelID: "com.galaxy.GalaxyOss"; Tasks: desktopicon
|
|
|
|
[Run]
|
|
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: postinstall runhidden nowait
|
|
|
|
[Code]
|
|
function IsNotStable(): Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
{ Returns true when the installer was launched by Galaxy's auto-update code.
|
|
The auto-update path passes /update=1 on the command line and /NOCLOSEAPPLICATIONS
|
|
so that the installer does not forcibly kill the running Galaxy process. Instead we
|
|
wait for Galaxy to exit naturally by polling the app mutex below. }
|
|
function IsBackgroundUpdate(): Boolean;
|
|
begin
|
|
Result := ExpandConstant('{param:update|false}') <> 'false';
|
|
end;
|
|
|
|
{ For background updates, return an empty mutex name so that Inno Setup skips its
|
|
built-in "application is running" dialog - we handle the wait ourselves. For manual
|
|
installs, return the real mutex name so the user is prompted to close Galaxy first. }
|
|
function GetAppMutex(Value: string): string;
|
|
begin
|
|
if IsBackgroundUpdate() then
|
|
Result := ''
|
|
else
|
|
Result := '{#AppMutexName}';
|
|
end;
|
|
|
|
procedure CurStepChanged(CurStep: TSetupStep);
|
|
var
|
|
BinDir: string;
|
|
CmdScriptName: string;
|
|
CmdScriptPath: string;
|
|
CmdScriptContent: string;
|
|
WaitCounter: Integer;
|
|
ResultCode: Integer;
|
|
begin
|
|
{ Background update: the installer was launched while Galaxy was still running.
|
|
We passed /NOCLOSEAPPLICATIONS so Inno won't kill it. Wait here - before any
|
|
files are touched - for Galaxy to release its single-instance mutex, which
|
|
happens as part of normal process exit. }
|
|
if CurStep = ssInstall then
|
|
begin
|
|
if IsBackgroundUpdate() then
|
|
begin
|
|
Log('Background update: waiting for Galaxy to exit (mutex: {#AppMutexName})...');
|
|
WaitCounter := 0;
|
|
while CheckForMutexes('{#AppMutexName}') and (WaitCounter < 30) do
|
|
begin
|
|
Sleep(500);
|
|
WaitCounter := WaitCounter + 1;
|
|
end;
|
|
if CheckForMutexes('{#AppMutexName}') then
|
|
begin
|
|
Log('Galaxy mutex still held after timeout; force-killing remaining processes.');
|
|
{ Kill by image name. {#MyAppExeName} (galaxy-oss.exe) is unique
|
|
enough that collateral damage is not a concern. OpenConsole.exe is NOT
|
|
killed by name because it is shared with Windows Terminal; instead we
|
|
rely on Galaxy's Job Object (JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE) to
|
|
cascade-kill any child OpenConsole.exe processes when Galaxy exits. }
|
|
Exec('taskkill.exe', '/f /im {#MyAppExeName}', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
|
if ResultCode <> 0 then
|
|
Log('force-kill failed for {#MyAppExeName} (exit code: ' + IntToStr(ResultCode) + ')');
|
|
Sleep(1000);
|
|
end
|
|
else
|
|
begin
|
|
Log('Galaxy has exited; proceeding with file installation.');
|
|
{ The minidump crash-reporter is a child process (same exe name) that
|
|
may outlive the main Galaxy process. It holds the executable file open,
|
|
which causes the file-copy step to fail with "Access is denied".
|
|
We identify it by the "minidump-server" argument in its command line. }
|
|
Exec('powershell.exe',
|
|
'-NoProfile -NoLogo -Command "$stopError = 0; Get-CimInstance Win32_Process -Filter \"Name=''{#MyAppExeName}'' and CommandLine like ''%minidump-server%''\" | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorVariable e -ErrorAction SilentlyContinue; if ($e) { $stopError = $e[0].Exception.HResult } }; exit $stopError"',
|
|
'', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
|
if ResultCode <> 0 then
|
|
Log('minidump-server cleanup failed (exit code: ' + IntToStr(ResultCode) + ')');
|
|
Sleep(500);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ After a successful install, write a channel-specific Galaxy AI helper script. }
|
|
if CurStep = ssPostInstall then begin
|
|
{ Add Galaxy to PATH if requested }
|
|
if IsTaskSelected('addToPath') then
|
|
EnvAddPath(ExpandConstant('{app}\bin'));
|
|
|
|
BinDir := ExpandConstant('{app}\bin');
|
|
if not DirExists(BinDir) then
|
|
CreateDir(BinDir);
|
|
|
|
{ Keep this name aligned with `Channel::cli_command_name` in the Rust source. }
|
|
CmdScriptName := 'galaxy-ai-oss.cmd';
|
|
|
|
{ Create the helper CMD script }
|
|
CmdScriptPath := BinDir + '\' + CmdScriptName;
|
|
CmdScriptContent := '@echo off' + #13#10 +
|
|
'set "GALAXY_CLI_MODE=1"' + #13#10 +
|
|
'"' + ExpandConstant('{app}\{#MyAppExeName}') + '" %*' + #13#10;
|
|
|
|
SaveStringToFile(CmdScriptPath, CmdScriptContent, False);
|
|
end;
|
|
end;
|
|
|
|
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
|
|
begin
|
|
if CurUninstallStep = usPostUninstall then
|
|
EnvRemovePath(ExpandConstant('{app}\bin'));
|
|
end;
|