Files
wehub-resource-sync 643e9f9fcb
.NET Tests / test-codebase (push) Waiting to run
Translation Validation / validate-translations (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:01:52 +08:00

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"