353 lines
14 KiB
Plaintext
353 lines
14 KiB
Plaintext
; Script generated by the Inno Setup Script Wizard.
|
|
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
|
|
|
#define MyAppVersion "3.3.7"
|
|
#define MyAppName "UniGetUI"
|
|
#define MyAppPublisher "Devolutions Inc."
|
|
#define MyAppURL "https://github.com/Devolutions/UniGetUI"
|
|
#define MyAppExeName "UniGetUI.exe"
|
|
#ifndef InstallerCompression
|
|
#define InstallerCompression "lzma"
|
|
#endif
|
|
|
|
#define public Dependency_Path_NetCoreCheck "InstallerExtras\"
|
|
#include "InstallerExtras\CodeDependencies.iss"
|
|
|
|
|
|
[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.)
|
|
UninstallDisplayName="UniGetUI"
|
|
AppId={{889610CC-4337-4BDB-AC3B-4F21806C0BDE}
|
|
AppName={#MyAppName}
|
|
AppVersion={#MyAppVersion}
|
|
AppVerName={#MyAppName} {#MyAppVersion}
|
|
AppPublisher={#MyAppPublisher}
|
|
AppPublisherURL="https://devolutions.net/unigetui/"
|
|
AppSupportURL={#MyAppURL}
|
|
AppUpdatesURL={#MyAppURL}
|
|
VersionInfoVersion=3.3.7.0
|
|
VersionInfoProductVersion=3.3.7.0
|
|
DefaultDirName="{autopf64}\UniGetUI"
|
|
DisableProgramGroupPage=yes
|
|
DisableDirPage=no
|
|
DirExistsWarning=no
|
|
; Force-close any process holding files we overwrite (backstop for the kill in PrepareToInstall).
|
|
CloseApplications=force
|
|
CloseApplicationsFilter=*.exe,*.dll
|
|
RestartApplications=no
|
|
; Default to per-user install mode and let the dialog opt into all-users installs when needed.
|
|
PrivilegesRequired=lowest
|
|
PrivilegesRequiredOverridesAllowed=dialog
|
|
OutputBaseFilename=UniGetUI Installer
|
|
OutputDir=.
|
|
; Comment line below to disable digital signature of installer
|
|
SignTool=azsign
|
|
|
|
SignedUninstaller=yes
|
|
SignedUninstallerDir=InstallerExtras\
|
|
MinVersion=10.0
|
|
SetupIconFile=src\SharedAssets\Assets\Images\icon.ico
|
|
UninstallDisplayIcon={app}\UniGetUI.exe
|
|
Compression={#InstallerCompression}
|
|
SolidCompression=yes
|
|
WizardStyle=modern dynamic
|
|
WizardImageFile=InstallerExtras\installer-banner.png
|
|
WizardImageFileDynamicDark=InstallerExtras\installer-banner.png
|
|
WizardSmallImageFile=InstallerExtras\unigetui-256.png
|
|
WizardSmallImageFileDynamicDark=InstallerExtras\unigetui-256.png
|
|
DisableWelcomePage=no
|
|
AllowUNCPath=no
|
|
UsePreviousTasks=yes
|
|
UsePreviousPrivileges=yes
|
|
UsePreviousAppDir=yes
|
|
ChangesEnvironment=yes
|
|
RestartIfNeededByRun=no
|
|
Uninstallable=WizardIsTaskSelected('regularinstall')
|
|
AppModifyPath="{app}\UniGetUI.Installer.exe" /silent /NoDeployInstaller
|
|
|
|
|
|
[Languages]
|
|
Name: "English"; MessagesFile: "compiler:Default.isl"
|
|
Name: "Armenian"; MessagesFile: "compiler:Languages\Armenian.isl"
|
|
Name: "BrazilianPortuguese"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
|
|
Name: "Catalan"; MessagesFile: "compiler:Languages\Catalan.isl"
|
|
Name: "Corsican"; MessagesFile: "compiler:Languages\Corsican.isl"
|
|
Name: "Czech"; MessagesFile: "compiler:Languages\Czech.isl"
|
|
Name: "Danish"; MessagesFile: "compiler:Languages\Danish.isl"
|
|
Name: "Dutch"; MessagesFile: "compiler:Languages\Dutch.isl"
|
|
Name: "Finnish"; MessagesFile: "compiler:Languages\Finnish.isl"
|
|
Name: "French"; MessagesFile: "compiler:Languages\French.isl"
|
|
Name: "German"; MessagesFile: "compiler:Languages\German.isl"
|
|
Name: "Hebrew"; MessagesFile: "compiler:Languages\Hebrew.isl"
|
|
;Name: "Icelandic"; MessagesFile: "compiler:Languages\Icelandic.isl"
|
|
Name: "Italian"; MessagesFile: "compiler:Languages\Italian.isl"
|
|
Name: "Japanese"; MessagesFile: "compiler:Languages\Japanese.isl"
|
|
Name: "Korean"; MessagesFile: "compiler:Languages\Korean.isl"
|
|
Name: "Norwegian"; MessagesFile: "compiler:Languages\Norwegian.isl"
|
|
Name: "Polish"; MessagesFile: "compiler:Languages\Polish.isl"
|
|
Name: "Portuguese"; MessagesFile: "compiler:Languages\Portuguese.isl"
|
|
Name: "Russian"; MessagesFile: "compiler:Languages\Russian.isl"
|
|
Name: "Slovenian"; MessagesFile: "compiler:Languages\Slovenian.isl"
|
|
Name: "Spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
|
|
Name: "Turkish"; MessagesFile: "compiler:Languages\Turkish.isl"
|
|
Name: "Ukrainian"; MessagesFile: "compiler:Languages\Ukrainian.isl"
|
|
|
|
; Include installer's messages
|
|
#include "InstallerExtras\CustomMessages.iss"
|
|
|
|
[Code]
|
|
var
|
|
PreserveAutostartDisabled: Boolean;
|
|
|
|
// StartupApproved stores the on/off state in the first byte's low bit (03 = off).
|
|
function IsAutostartDisabledByUser: Boolean;
|
|
var
|
|
Data: AnsiString;
|
|
begin
|
|
Result := False;
|
|
if RegQueryBinaryValue(HKEY_CURRENT_USER,
|
|
'Software\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run',
|
|
'WingetUI', Data) then
|
|
Result := (Length(Data) >= 1) and ((Ord(Data[1]) and 1) = 1);
|
|
end;
|
|
|
|
procedure InitializeWizard;
|
|
begin
|
|
WizardForm.Bevel.Visible := False;
|
|
WizardForm.Bevel1.Visible := True;
|
|
end;
|
|
|
|
// Kills all instances of an image and loops until none remain (taskkill returns 0 while killing, 128 when none left).
|
|
procedure TaskKillWait(FileName: String);
|
|
var
|
|
ResultCode, Attempts: Integer;
|
|
begin
|
|
Attempts := 0;
|
|
repeat
|
|
if not Exec('taskkill.exe', '/f /im "' + FileName + '"', '', SW_HIDE,
|
|
ewWaitUntilTerminated, ResultCode) then
|
|
Break;
|
|
if ResultCode <> 0 then
|
|
Break;
|
|
Sleep(500);
|
|
Attempts := Attempts + 1;
|
|
until Attempts >= 10;
|
|
end;
|
|
|
|
procedure KillRunningApps;
|
|
begin
|
|
TaskKillWait('WingetUI.exe');
|
|
TaskKillWait('UniGetUI.exe');
|
|
TaskKillWait('UniGetUI.Avalonia.exe');
|
|
// Elevator (gsudo cache) and pinget live in {app} and lock their own files.
|
|
TaskKillWait('UniGetUI Elevator.exe');
|
|
TaskKillWait('pinget.exe');
|
|
Sleep(1000); // let the OS release file handles before copying
|
|
|
|
end;
|
|
|
|
function GetCurrentProcessId: Cardinal; external 'GetCurrentProcessId@kernel32.dll stdcall';
|
|
|
|
function UpdateMarkerPath(): String;
|
|
begin
|
|
Result := ExpandConstant('{app}\.unigetui-update-in-progress');
|
|
end;
|
|
|
|
// Marker holds our PID; the app blocks only while this installer runs. Name MUST match UpdateInProgressGuard.MarkerFileName.
|
|
procedure WriteUpdateMarker;
|
|
var
|
|
Pid: Int64;
|
|
begin
|
|
ForceDirectories(ExpandConstant('{app}'));
|
|
Pid := GetCurrentProcessId;
|
|
SaveStringToFile(UpdateMarkerPath(), IntToStr(Pid), False);
|
|
end;
|
|
|
|
procedure RemoveUpdateMarker;
|
|
begin
|
|
DeleteFile(UpdateMarkerPath());
|
|
end;
|
|
|
|
// Runs before any file is copied: shut everything down, then mark the copy window.
|
|
function PrepareToInstall(var NeedsRestart: Boolean): String;
|
|
begin
|
|
// Capture before [Registry] rewrites the Run key, so updates keep the user's choice.
|
|
PreserveAutostartDisabled := IsAutostartDisabledByUser;
|
|
KillRunningApps;
|
|
WriteUpdateMarker;
|
|
Result := '';
|
|
end;
|
|
|
|
// Clear the marker once the copy is done, before the post-install launch.
|
|
procedure CurStepChanged(CurStep: TSetupStep);
|
|
begin
|
|
if CurStep = ssPostInstall then
|
|
RemoveUpdateMarker;
|
|
end;
|
|
|
|
function CmdLineParamExists(const Value: string): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
for I := 1 to ParamCount do
|
|
if CompareText(ParamStr(I), Value) = 0 then
|
|
begin
|
|
Result := True;
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
function IsMSStoreInstall: Boolean;
|
|
begin
|
|
Result := CmdLineParamExists('/MSStore');
|
|
end;
|
|
|
|
function ShouldInstallVCRedist: Boolean;
|
|
begin
|
|
Result := not (CmdLineParamExists('/NoVCRedist') or IsMSStoreInstall);
|
|
end;
|
|
|
|
function ShouldInstallEdgeWebView: Boolean;
|
|
begin
|
|
Result := not (CmdLineParamExists('/NoEdgeWebView') or IsMSStoreInstall);
|
|
end;
|
|
|
|
function ShouldLaunchAfterInstall: Boolean;
|
|
begin
|
|
Result := not (CmdLineParamExists('/NoAutoStart') or IsMSStoreInstall);
|
|
end;
|
|
|
|
function ShouldSuppressRunOnStartup: Boolean;
|
|
begin
|
|
Result := CmdLineParamExists('/NoRunOnStartup') or IsMSStoreInstall or PreserveAutostartDisabled;
|
|
end;
|
|
|
|
var CustomExitCode: integer;
|
|
|
|
procedure ExitProcess(exitCode:integer);
|
|
external 'ExitProcess@kernel32.dll stdcall';
|
|
|
|
procedure DeinitializeSetup();
|
|
begin
|
|
RemoveUpdateMarker; // also clear on abort, before ssPostInstall
|
|
|
|
if (CustomExitCode <> 0) then
|
|
begin
|
|
DelTree(ExpandConstant('{tmp}'), True, True, True);
|
|
ExitProcess(0);
|
|
end;
|
|
end;
|
|
|
|
function IsCharValid(Value: Char): Boolean;
|
|
begin
|
|
Result := Ord(Value) <= $007F;
|
|
end;
|
|
|
|
function IsDirNameValid(const Value: string): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
for I := 1 to Length(Value) do
|
|
if not IsCharValid(Value[I]) then
|
|
Exit;
|
|
Result := True;
|
|
end;
|
|
|
|
function NextButtonClick(CurPageID: Integer): Boolean;
|
|
begin
|
|
Result := True;
|
|
|
|
if (CurPageID = wpSelectDir) and
|
|
not IsDirNameValid(WizardForm.DirEdit.Text) then
|
|
begin
|
|
Result := False;
|
|
MsgBox('There is an invalid character in the selected install location. ' +
|
|
'Install location cannot contain special characters. ' +
|
|
'Please input a valid path to continue, such as '+ExpandConstant('{commonpf64}')+'\UniGetUI', mbError, MB_OK);
|
|
end;
|
|
end;
|
|
|
|
function InitializeSetup: Boolean;
|
|
begin
|
|
try
|
|
if ShouldInstallVCRedist then
|
|
begin
|
|
Dependency_AddVC2015To2022;
|
|
end;
|
|
if ShouldInstallEdgeWebView then
|
|
begin
|
|
Dependency_AddWebView2;
|
|
end;
|
|
Result := True;
|
|
except
|
|
Result := True;
|
|
end;
|
|
end;
|
|
|
|
|
|
[Tasks]
|
|
Name: "portableinstall"; Description: "{cm:PortInst}"; GroupDescription: "{cm:InstallType}"; Flags: unchecked exclusive
|
|
Name: "regularinstall"; Description: "{cm:RegInst}"; GroupDescription: "{cm:InstallType}"; Flags: exclusive
|
|
Name: "regularinstall\startmenuicon"; Description: "{cm:RegStartMmenuIcon}"; GroupDescription: "{cm:ShCuts}";
|
|
Name: "regularinstall\desktopicon"; Description: "{cm:RegDesktopIcon}"; GroupDescription: "{cm:ShCuts}";
|
|
|
|
[Registry]
|
|
Root: HKCU; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; ValueType: string; ValueName: "WingetUI"; ValueData: """{app}\UniGetUI.exe"" --daemon"; Flags: uninsdeletevalue noerror; Tasks: regularinstall;
|
|
Root: HKCU; Subkey: "Software\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run"; ValueType: binary; ValueName: "WingetUI"; ValueData: "03"; Flags: uninsdeletevalue; Tasks: regularinstall; Check: ShouldSuppressRunOnStartup;
|
|
|
|
// Register the unigetui:// deep link
|
|
Root: HKA; Subkey: "Software\Classes\unigetui"; ValueType: "string"; ValueData: "URL:UniGetUI Protocol"; Flags: uninsdeletekey; Tasks: regularinstall;
|
|
Root: HKA; Subkey: "Software\Classes\unigetui"; ValueType: "string"; ValueName: "URL Protocol"; ValueData: ""; Tasks: regularinstall;
|
|
Root: HKA; Subkey: "Software\Classes\unigetui\DefaultIcon"; ValueType: "string"; ValueData: "{app}\{#MyAppExeName},0"; Tasks: regularinstall;
|
|
Root: HKA; Subkey: "Software\Classes\unigetui\shell\open\command"; ValueType: "string"; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Tasks: regularinstall;
|
|
|
|
// Register the .ubundle file type
|
|
Root: HKA; Subkey: "Software\Classes\.ubundle"; ValueType: string; ValueData: "UniGetUI.PackageBundle"; Flags: uninsdeletekey; Tasks: regularinstall;
|
|
Root: HKA; Subkey: "Software\Classes\UniGetUI.PackageBundle"; ValueType: string; ValueData: {cm:PackageBundleName}; Flags: uninsdeletekey; Tasks: regularinstall;
|
|
Root: HKA; Subkey: "Software\Classes\UniGetUI.PackageBundle\DefaultIcon"; ValueType: string; ValueData: "{app}\{#MyAppExeName},0"; Flags: uninsdeletekey; Tasks: regularinstall;
|
|
Root: HKA; Subkey: "Software\Classes\UniGetUI.PackageBundle\shell\open\command"; ValueType: string; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey; Tasks: regularinstall;
|
|
|
|
|
|
[InstallDelete]
|
|
Type: filesandordirs; Name: "{app}\Avalonia"
|
|
Type: filesandordirs; Name: "{app}\Assets"
|
|
Type: files; Name: "{app}\WingetUI.exe"
|
|
Type: files; Name: "{app}\UniGetUI.Avalonia.exe"
|
|
Type: files; Name: "{app}\*.dll"
|
|
Type: files; Name: "{app}\*.pdb"
|
|
Type: files; Name: "{app}\*.pri"
|
|
Type: files; Name: "{app}\*.xbf"
|
|
Type: files; Name: "{app}\*.json"
|
|
|
|
[Files]
|
|
; Deploy installer for autorepair jobs (unless disabled)
|
|
Source: "{srcexe}"; DestDir: "{app}"; DestName: "UniGetUI.Installer.exe"; Flags: external ignoreversion; Tasks: regularinstall; Check: not CmdLineParamExists('/NoDeployInstaller');
|
|
; Deploy integrity tree
|
|
Source: "unigetui_bin\IntegrityTree.json"; DestDir: "{app}"; Flags: createallsubdirs ignoreversion recursesubdirs;
|
|
; Deploy executable files (running instances already killed in PrepareToInstall).
|
|
Source: "unigetui_bin\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion;
|
|
Source: "unigetui_bin\*"; DestDir: "{app}"; Flags: createallsubdirs ignoreversion recursesubdirs;
|
|
; Make installation portable (if required)
|
|
Source: "InstallerExtras\ForceUniGetUIPortable"; DestDir: "{app}"; Tasks: portableinstall
|
|
|
|
|
|
[Icons]
|
|
Name: "{autostartmenu}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: regularinstall\startmenuicon
|
|
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: regularinstall\desktopicon
|
|
|
|
[Run]
|
|
; Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File -NonInteractive ""{tmp}\EnsureWinGet.ps1"""; StatusMsg: "Ensuring WinGet is properly installed... (this may take a while)"; WorkingDir: {app}; Check: not CmdLineParamExists('/NoWinGet'); Flags: runhidden
|
|
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: runasoriginaluser nowait postinstall; Check: ShouldLaunchAfterInstall;
|
|
Filename: "{app}\{#MyAppExeName}"; Parameters: "--migrate-wingetui-to-unigetui"; StatusMsg: "Removing old icons...";
|
|
|
|
|
|
[UninstallRun]
|
|
; Remove WingetUI Notification registries
|
|
; Filename: "{app}\{#MyAppExeName}"; Parameters: "--uninstall-unigetui"; Flags: skipifdoesntexist runhidden;
|
|
Filename: {sys}\taskkill.exe; Parameters: "/f /im WingetUI.exe"; Flags: skipifdoesntexist runhidden; RunOnceId: "KillWingetUI"
|
|
Filename: {sys}\taskkill.exe; Parameters: "/f /im UniGetUI.exe"; Flags: skipifdoesntexist runhidden; RunOnceId: "KillUniGetUI"
|
|
Filename: {sys}\taskkill.exe; Parameters: "/f /im UniGetUI.Avalonia.exe"; Flags: skipifdoesntexist runhidden; RunOnceId: "KillUniGetUIAvalonia"
|