; AUTOGENERATED COPYRIGHT HEADER START ; Copyright (C) 2022-2023 Michael Fabian 'Xaymar' Dirks ; AUTOGENERATED COPYRIGHT HEADER END #define MyAppName "@PROJECT_TITLE@" #define MyAppVersion "@PROJECT_VERSION@" #define MyAppVersionText "@_VERSION@" #define MyAppPublisher "Xaymars Technology Workshop" #define MyAppURL "https://xaymar.com/" #define MyAppCopyright "@PROJECT_COPYRIGHT@" [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.) ; Application Information AppId={{DE56A03A-C8A4-474B-83B0-CFD270262D38}} AppName={#MyAppName} AppVersion={#MyAppVersion} AppPublisher={#MyAppPublisher} AppPublisherURL={#MyAppURL} AppSupportURL={#MyAppURL} AppUpdatesURL={#MyAppURL} AppMutex=@PROJECT_NAME@,Global\@PROJECT_NAME@ ; Versioning VersionInfoProductName={#MyAppName} VersionInfoProductVersion={#MyAppVersion} VersionInfoVersion={#MyAppVersion} VersionInfoProductTextVersion={#MyAppVersionText} VersionInfoTextVersion={#MyAppVersionText} VersionInfoCompany={#MyAppPublisher} VersionInfoCopyright={#MyAppCopyright} VersionInfoDescription={#MyAppName} Setup ; Architecture (Platform is always Windows) ArchitecturesInstallIn64BitMode=x64 arm64 ia64 ArchitecturesAllowed=@ARCH@ ; Installation Modes AlwaysShowComponentsList=no UsePreviousTasks=no UsePreviousSetupType=no UsePreviousPrivileges=no PrivilegesRequired=admin PrivilegesRequiredOverridesAllowed=dialog commandline ; Wizard Information WizardStyle=modern WizardResizable=yes SetupIconFile="@PROJECT_SOURCE_DIR@/media/icon.ico" SetupMutex=@PROJECT_NAME@-Setup,Global\@PROJECT_NAME@-Setup UninstallDisplayIcon={uninstallexe} ; Directory Choices UsePreviousAppDir=no DisableDirPage=no DirExistsWarning=no DefaultDirName={code:GetDefaultDirectory} AppendDefaultDirName=yes DisableProgramGroupPage=no DefaultGroupName={#MyAppName} AppendDefaultGroupName=yes ; Other Information Uninstallable=yes CreateUninstallRegKey=not IsPortableMode() ChangesEnvironment=yes AllowNoIcons=yes LicenseFile="@ISS_SOURCE_DIR@/LICENSE" OutputDir="@ISS_PACKAGE_DIR@" OutputBaseFilename=@PACKAGE_NAME@-@_PACKAGE_SUFFIX_OVERRIDE@ Compression=lzma2/ultra64 SolidCompression=yes LZMAAlgorithm=1 [Languages] Name: "english"; MessagesFile: "compiler:Default.isl" [Components] name: "startmenu"; Description: "Start Menu Entries" [Files] Source: "@ISS_FILES_DIR@/data/obs-plugins/@PROJECT_NAME@/*"; DestDir: "{code:GetOutputDataDir}"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "@ISS_FILES_DIR@/obs-plugins/@D_PLATFORM_BITS@bit/*"; DestDir: "{code:GetOutputBinaryDir}"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "@PROJECT_SOURCE_DIR@/templates/windows/msvc-redist-helper.exe"; DestDir: "{app}"; DestName: "msvc-redist-helper.exe"; Flags: ignoreversion dontcopy noencryption ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Icons] Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}"; Components: startmenu Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"; Components: startmenu [Code] // ------------------------------------------------------------------------------------------------------------------ // #ifdef UNICODE #define AW "W" #else #define AW "A" #endif type WPARAM = UINT_PTR; LPARAM = INT_PTR; LRESULT = INT_PTR; const SMTO_ABORTIFHUNG = 2; WM_WININICHANGE = $001A; WM_SETTINGCHANGE = WM_WININICHANGE; function user32_SendTextMessageTimeoutA( hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: PAnsiChar; fuFlags: UINT; uTimeout: UINT; out lpdwResult: DWORD): LRESULT; external 'SendMessageTimeoutA@user32.dll stdcall'; procedure RefreshEnvironment(); var S: AnsiString; MsgResult: DWORD; begin S := 'Environment'; user32_SendTextMessageTimeoutA(HWND_BROADCAST, WM_SETTINGCHANGE, 0, PAnsiChar(S), SMTO_ABORTIFHUNG, 5000, MsgResult); end; // ------------------------------------------------------------------------------------------------------------------ // function ParamExists(Name: String): Boolean; var Idx: Integer; Limit: Integer; Param: String; begin Limit := ParamCount() for Idx := 1 to Limit do begin Param := ParamStr(Idx); if SameText(Param, '/' + Name) then begin Result := True; exit; end; end; Result := False; end; // ------------------------------------------------------------------------------------------------------------------ // var oModePageSystemChoice: TNewRadioButton; oModePageUserChoice: TNewRadioButton; oModePagePortableChoice: TNewRadioButton; bIsPortableMode: Boolean; bIsUserMode: Boolean; bIsSystemMode: Boolean; // InnoSetup procedure InitializeWizard; forward; function ShouldSkipPage(PageID: Integer): Boolean; forward; function PrepareToInstall(var NeedsRestart: Boolean): String; forward; function GetDefaultDirectory(Value: String): String; forward; function GetOutputBinaryDir(Value: String): String; forward; function GetOutputDataDir(Value: String): String; forward; // Which installation is present? function IsSystemInstallPresent(): Boolean; forward; function GetSystemUninstaller(): String; forward; function IsUserInstallPresent(): Boolean; forward; function GetUserUninstaller(): String; forward; // Which installation mode is selected? function IsSystemMode(): Boolean; forward; function IsUserMode(): Boolean; forward; function IsPortableMode(): Boolean; forward; // Other Metadata function AppRegistryKey(): String; forward; function GetUninstallerPath(): String; forward; function IsUpgrade(): Boolean; forward; function UninstallOldVersion(): Integer; forward; // Mode Page function CreateModePage: TWizardPage; forward; procedure OnModePagePortableChoiceClick(Sender: TObject); forward; procedure OnModePageSystemChoiceClick(Sender: TObject); forward; // ------------------------------------------------------------------------------------------------------------------ // function InitializeSetup(): Boolean; begin if ParamExists('Portable') then begin bIsSystemMode := False; bIsUserMode := False; bIsPortableMode := True; end else begin bIsSystemMode := IsAdmin(); bIsUserMode := not IsAdmin(); bIsPortableMode := False; end; Result := True; end; // ------------------------------------------------------------------------------------------------------------------ // procedure InitializeWizard; var oModePage: TWizardPage; begin oModePage := CreateModePage(); if (IsPortableMode()) then begin WizardSelectComponents('!startmenu'); end else begin WizardSelectComponents('startmenu'); end; end; // ------------------------------------------------------------------------------------------------------------------ // function ShouldSkipPage(PageID: Integer): Boolean; begin Result := False; if (PageID = wpSelectDir) then begin Result := not IsPortableMode(); end else if (PageID = wpSelectComponents) then begin Result := True; end else if (PageID = wpSelectProgramGroup) then begin Result := not WizardIsComponentSelected('startmenu'); end; end; // ------------------------------------------------------------------------------------------------------------------ // function PrepareToInstall(var NeedsRestart: Boolean): String; var iResultCode: Integer; sPluginsPath: String; sPluginsDataPath: String; begin // Attempt to remove old version if it exists. if (IsUpgrade()) then begin if (UninstallOldVersion() != 0) then begin Result := "Removal of older @PROJECT_NAME@ version was cancelled. Unable to continue with normal installation process, Setup will now abort." exit; end end; // Also ensure that we have the necessary prerequisites installed to run the program. ExtractTemporaryFile('msvc-redist-helper.exe'); Exec(ExpandConstant('{tmp}\msvc-redist-helper.exe'), '2019', '', SW_HIDE, ewWaitUntilTerminated, iResultCode); // If this is a User install, register the necessary environment changes. if (IsUserMode()) then begin sPluginsPath := ExpandConstant('{usercf}\obs-studio\plugins\%module%\bin\'); StringChangeEx(sPluginsPath, '\', '/', True); RegWriteExpandStringValue(HKEY_CURRENT_USER, 'Environment', 'OBS_PLUGINS_PATH', sPluginsPath); sPluginsDataPath := ExpandConstant('{usercf}\obs-studio\plugins\%module%\data\'); StringChangeEx(sPluginsDataPath, '\', '/', True); RegWriteExpandStringValue(HKEY_CURRENT_USER, 'Environment', 'OBS_PLUGINS_DATA_PATH', sPluginsDataPath); RefreshEnvironment(); end; end; // ------------------------------------------------------------------------------------------------------------------ // function GetDefaultDirectory(Value: String): String; var sPath: String; begin // In all other cases, change depending on the chosen install method. if (IsSystemMode()) then begin // Default to ProgramData/obs-studio/@PROJECT_NAME@ Result := ExpandConstant('{commonappdata}\obs-studio\plugins\@PROJECT_NAME@'); end else if (IsUserMode()) then begin Result := ExpandConstant('{usercf}\obs-studio\plugins\@PROJECT_NAME@'); end else begin // If a path was given as an argument, use it. if (Value <> '') then begin Result := Value; exit; end; Result := ExpandConstant('{userdesktop}\obs-studio'); end; end; // ------------------------------------------------------------------------------------------------------------------ // function GetOutputBinaryDir(Value: String): String; var sPath: String; begin if (IsSystemMode()) then begin sPath := ExpandConstant('{app}\bin\@D_PLATFORM_BITS@bit\'); end else if (IsUserMode()) then begin sPath := ExpandConstant('{app}\bin\'); end else if (IsPortableMode()) then begin sPath := ExpandConstant('{app}\obs-plugins\@D_PLATFORM_BITS@bit\'); end; Result := sPath; end; function GetOutputDataDir(Value: String): String; var sPath: String; begin if (IsSystemMode()) then begin sPath := ExpandConstant('{app}\data\'); end else if (IsUserMode()) then begin sPath := ExpandConstant('{app}\data\@PROJECT_NAME@\'); end else if (IsPortableMode()) then begin sPath := ExpandConstant('{app}\data\obs-plugins\@PROJECT_NAME@\'); end; Result := sPath; end; // ------------------------------------------------------------------------------------------------------------------ // function GetSystemUninstaller(): String; var sPath : String; begin Result := ''; if (RegQueryStringValue(HKLM64, AppRegistryKey(), 'UninstallString', sPath)) then begin Result := sPath; end; end; function IsSystemInstallPresent(): Boolean; var sPath : String; begin sPath := GetSystemUninstaller(); if (sPath <> '') then begin Result := True; end else begin Result := False; end; end; function GetUserUninstaller(): String; var sPath : String; begin Result := ''; if (RegQueryStringValue(HKCU64, AppRegistryKey(), 'UninstallString', sPath)) then begin Result := sPath; end; end; function IsUserInstallPresent(): Boolean; var sPath : String; begin sPath := GetUserUninstaller(); if (sPath <> '') then begin Result := True; end else begin Result := False; end; end; function GetUninstallerPath(): String; begin if (IsSystemMode()) then begin Result := GetSystemUninstaller(); end else if (IsUserMode()) then begin Result := GetUserUninstaller(); end else begin Result := ''; end; end; // ------------------------------------------------------------------------------------------------------------------ // function IsSystemMode(): Boolean; begin Result := bIsSystemMode; end; function IsUserMode(): Boolean; begin Result := bIsUserMode; end; function IsPortableMode(): Boolean; begin Result := bIsPortableMode; end; // ------------------------------------------------------------------------------------------------------------------ // function AppRegistryKey(): String; begin Result := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting('AppId')}_is1'); end; // ------------------------------------------------------------------------------------------------------------------ // function IsUpgrade(): Boolean; begin Result := (not IsPortableMode()) and (GetUninstallerPath() <> ''); end; // ------------------------------------------------------------------------------------------------------------------ // function UninstallOldVersion(): Integer; var sUninstallerPath: String; iResultCode: Integer; begin Result := 0; sUninstallerPath := GetUninstallerPath(); if (sUninstallerPath <> '') then begin sUninstallerPath := RemoveQuotes(sUninstallerPath); if Exec(sUninstallerPath, '', '', SW_HIDE, ewWaitUntilTerminated, iResultCode) then begin Result := iResultCode end else begin Result := 1 end; end; end; // ------------------------------------------------------------------------------------------------------------------ // procedure OnModePageSystemChoiceClick(Sender: TObject); begin if (not oModePageSystemChoice.Enabled) then begin OnModePagePortableChoiceClick(Sender); end else begin oModePageSystemChoice.Checked := True; oModePageUserChoice.Checked := False; oModePagePortableChoice.Checked := False; bIsSystemMode := True; bIsUserMode := False; bIsPortableMode := False; WizardSelectComponents('startmenu'); end; end; procedure onModePageUserChoiceClick(Sender: TObject); begin if (not oModePageUserChoice.Enabled) then begin OnModePagePortableChoiceClick(Sender); end else begin oModePageSystemChoice.Checked := False; oModePageUserChoice.Checked := True; oModePagePortableChoice.Checked := False; bIsSystemMode := False; bIsUserMode := True; bIsPortableMode := False; WizardSelectComponents('startmenu'); end; end; procedure OnModePagePortableChoiceClick(Sender: TObject); begin oModePageSystemChoice.Checked := False; oModePageUserChoice.Checked := False; oModePagePortableChoice.Checked := True; bIsSystemMode := False; bIsUserMode := False; bIsPortableMode := True; WizardSelectComponents('!startmenu'); end; function CreateModePage: TWizardPage; var oPage: TWizardPage; oSystemPanel: TPanel; oSystemChoice: TNewRadioButton; oSystemText: TLabel; oSystemWarningText: TLabel; oUserPanel: TPanel; oUserChoice: TNewRadioButton; oUserText: TLabel; oUserWarningText: TLabel; oPortablePanel: TPanel; oPortableChoice: TNewRadioButton; oPortableText: TLabel; oPortableWarningText: TLabel; oFractionalHeight: Integer; begin // Build a page that asks a user if they want to use Movable or Static installation. oPage := CreateCustomPage(wpLicense, 'Installation Mode', 'Select how to install StreamFX on your System'); oFractionalHeight := ScaleY((oPage.SurfaceHeight - 10) / 3); // System-Wide installation if (True) then begin oSystemPanel := TPanel.Create(oPage); oSystemPanel.Parent := oPage.Surface; oSystemPanel.ParentBackground := False; oSystemPanel.Left := ScaleX(5); oSystemPanel.Top := ScaleY(5); oSystemPanel.Width := oPage.SurfaceWidth - ScaleX(10); oSystemPanel.Height := oFractionalHeight; oSystemPanel.Anchors := [akLeft, akTop, akRight]; oSystemPanel.Color := clWindow; oSystemPanel.BevelKind := bkTile; oSystemPanel.BevelInner := bvNone; oSystemPanel.BevelOuter := bvRaised; oSystemPanel.BevelWidth := 1; oSystemPanel.OnClick := @OnModePageSystemChoiceClick; oSystemChoice := TNewRadioButton.Create(oSystemPanel); oModePageSystemChoice := oSystemChoice; oSystemChoice.Parent := oSystemPanel; oSystemChoice.ParentBackground := False; oSystemChoice.Left := ScaleX(5); oSystemChoice.Top := ScaleY(5); oSystemChoice.Width := oSystemPanel.Width - ScaleX(10); oSystemChoice.Height := ScaleY(20); oSystemChoice.Anchors := [akLeft, akTop, akRight]; oSystemChoice.Caption := 'All Users'; oSystemChoice.Font.Style := [fsBold]; oSystemChoice.OnClick := @OnModePageSystemChoiceClick; oSystemText := TLabel.Create(oSystemPanel); oSystemText.Parent := oSystemPanel; oSystemText.AutoSize := False; oSystemText.Left := ScaleX(5); oSystemText.Top := ScaleY(5) + oSystemChoice.Top + oSystemChoice.Height; oSystemText.Width := oSystemPanel.Width - ScaleX(10); oSystemText.Height := oSystemPanel.Height - ScaleX(5) - oSystemText.Top; oSystemText.Anchors := [akLeft, akTop, akRight]; oSystemText.WordWrap := True oSystemText.Caption := 'Install for all users of this System, which will require Administrator rights for future updates. May cause problems with Portable and Current User installations.'; oSystemText.OnClick := @OnModePageSystemChoiceClick; // Not available without Administrator rights. if (not IsAdmin()) then begin oSystemWarningText := TLabel.Create(oSystemPanel); oSystemWarningText.Parent := oSystemPanel; oSystemWarningText.AutoSize := False; oSystemWarningText.Left := ScaleX(5); oSystemWarningText.Top := oSystemPanel.Height - ScaleY(5) - ScaleY(15); oSystemWarningText.Width := oSystemPanel.Width - ScaleX(10); oSystemWarningText.Height := ScaleY(15); oSystemWarningText.Anchors := [akLeft, akBottom, akRight]; oSystemWarningText.WordWrap := True oSystemWarningText.Font.Color := clRed; oSystemWarningText.Font.Style := [fsBold]; oSystemWarningText.Caption := 'Please launch the installer with Administrator rights.'; oSystemPanel.Enabled := False; oSystemChoice.Enabled := False; oSystemChoice.Checked := False; oSystemText.Enabled := False; end else if (IsUserInstallPresent()) then begin oSystemWarningText := TLabel.Create(oSystemPanel); oSystemWarningText.Parent := oSystemPanel; oSystemWarningText.AutoSize := False; oSystemWarningText.Left := ScaleX(5); oSystemWarningText.Top := oSystemPanel.Height - ScaleY(5) - ScaleY(15); oSystemWarningText.Width := oSystemPanel.Width - ScaleX(10); oSystemWarningText.Height := ScaleY(15); oSystemWarningText.Anchors := [akLeft, akBottom, akRight]; oSystemWarningText.WordWrap := True oSystemWarningText.Font.Color := $007EFF; oSystemWarningText.Font.Style := [fsBold]; oSystemWarningText.Caption := 'A conflicting installation was detected which may cause issues.'; end; end; // Local-User installation if (True) then begin oUserPanel := TPanel.Create(oPage); oUserPanel.Parent := oPage.Surface; oUserPanel.ParentBackground := False; oUserPanel.Left := ScaleX(5); oUserPanel.Top := ScaleY(5) + oSystemPanel.Top + oSystemPanel.Height; oUserPanel.Width := oPage.SurfaceWidth - ScaleX(10); oUserPanel.Height := oFractionalHeight; oUserPanel.Anchors := [akLeft, akTop, akRight]; oUserPanel.Color := clWindow; oUserPanel.BevelKind := bkTile; oUserPanel.BevelInner := bvNone; oUserPanel.BevelOuter := bvRaised; oUserPanel.BevelWidth := 1; oUserPanel.OnClick := @OnModePageUserChoiceClick; oUserChoice := TNewRadioButton.Create(oUserPanel); oModePageUserChoice := oUserChoice; oUserChoice.Parent := oUserPanel; oUserChoice.ParentBackground := False; oUserChoice.Left := ScaleX(5); oUserChoice.Top := ScaleY(5); oUserChoice.Width := oUserPanel.Width - ScaleX(10); oUserChoice.Height := ScaleY(20); oUserChoice.Anchors := [akLeft, akTop, akRight]; oUserChoice.Caption := 'Current User'; oUserChoice.Font.Style := [fsBold]; oUserChoice.OnClick := @OnModePageUserChoiceClick; oUserText := TLabel.Create(oUserPanel); oUserText.Parent := oUserPanel; oUserText.AutoSize := False; oUserText.Left := ScaleX(5); oUserText.Top := ScaleY(5) + oUserChoice.Top + oUserChoice.Height; oUserText.Width := oUserPanel.Width - ScaleX(10); oUserText.Height := oUserPanel.Height - ScaleX(5) - oUserText.Top; oUserText.Anchors := [akLeft, akTop, akRight]; oUserText.WordWrap := True oUserText.Caption := 'Install for the current user only, which will allow you to use @PROJECT_NAME@. Updating will not require Administrator rights.'; oUserText.OnClick := @OnModePageUserChoiceClick; // Not available with Administrator rights. if (IsAdmin()) then begin oUserWarningText := TLabel.Create(oUserPanel); oUserWarningText.Parent := oUserPanel; oUserWarningText.AutoSize := False; oUserWarningText.Left := ScaleX(5); oUserWarningText.Top := oUserPanel.Height - ScaleY(5) - ScaleY(15); oUserWarningText.Width := oUserPanel.Width - ScaleX(10); oUserWarningText.Height := ScaleY(15); oUserWarningText.Anchors := [akLeft, akBottom, akRight]; oUserWarningText.WordWrap := True oUserWarningText.Font.Color := clRed; oUserWarningText.Font.Style := [fsBold]; oUserWarningText.Caption := 'Please launch the Installer without Administrator rights.'; oUserPanel.Enabled := False; oUserChoice.Enabled := False; oUserChoice.Checked := False; oUserText.Enabled := False; end else if (IsSystemInstallPresent()) then begin oUserWarningText := TLabel.Create(oUserPanel); oUserWarningText.Parent := oUserPanel; oUserWarningText.AutoSize := False; oUserWarningText.Left := ScaleX(5); oUserWarningText.Top := oUserPanel.Height - ScaleY(5) - ScaleY(15); oUserWarningText.Width := oUserPanel.Width - ScaleX(10); oUserWarningText.Height := ScaleY(15); oUserWarningText.Anchors := [akLeft, akBottom, akRight]; oUserWarningText.WordWrap := True oUserWarningText.Font.Color := $007EFF; oUserWarningText.Font.Style := [fsBold]; oUserWarningText.Caption := 'A conflicting system wide installation was detected.'; oUserPanel.Enabled := False; oUserChoice.Enabled := False; oUserChoice.Checked := False; oUserText.Enabled := False; end; end; // Portable if (True) then begin oPortablePanel := TPanel.Create(oPage); oPortablePanel.Parent := oPage.Surface; oPortablePanel.ParentBackground := False; oPortablePanel.Left := ScaleX(5); oPortablePanel.Top := ScaleY(5) + oUserPanel.Top + oUserPanel.Height; oPortablePanel.Width := oPage.SurfaceWidth - ScaleX(10); oPortablePanel.Height := oFractionalHeight; oPortablePanel.Anchors := [akLeft, akTop, akRight]; oPortablePanel.Color := clWindow; oPortablePanel.BevelKind := bkTile; oPortablePanel.BevelInner := bvNone; oPortablePanel.BevelOuter := bvRaised; oPortablePanel.BevelWidth := 1; oPortablePanel.OnClick := @OnModePagePortableChoiceClick; oPortableChoice := TNewRadioButton.Create(oPortablePanel); oModePagePortableChoice := oPortableChoice; oPortableChoice.Parent := oPortablePanel; oPortableChoice.ParentBackground := False; oPortableChoice.Left := ScaleX(5); oPortableChoice.Top := ScaleY(5); oPortableChoice.Width := oPortablePanel.Width - ScaleX(10); oPortableChoice.Height := ScaleY(20); oPortableChoice.Anchors := [akLeft, akTop, akRight]; oPortableChoice.Caption := 'Portable'; oPortableChoice.Font.Style := [fsBold]; oPortableChoice.OnClick := @OnModePagePortableChoiceClick; oPortableText := TLabel.Create(oPortablePanel); oPortableText.Parent := oPortablePanel; oPortableText.AutoSize := False; oPortableText.Left := ScaleX(5); oPortableText.Top := ScaleY(5) + oPortableChoice.Top + oPortableChoice.Height; oPortableText.Width := oPortablePanel.Width - ScaleX(10); oPortableText.Height := oPortablePanel.Height - ScaleX(5) - oPortableText.Top; oPortableText.Anchors := [akLeft, akTop, akRight]; oPortableText.WordWrap := True oPortableText.Caption := 'Install for a portable OBS Studio environment.'; oPortableText.OnClick := @OnModePagePortableChoiceClick; // Warn about Administrator rights if (IsAdmin()) then begin oPortableWarningText := TLabel.Create(oPortablePanel); oPortableWarningText.Parent := oPortablePanel; oPortableWarningText.AutoSize := False; oPortableWarningText.Left := ScaleX(5); oPortableWarningText.Top := oPortablePanel.Height - ScaleY(5) - ScaleY(15); oPortableWarningText.Width := oPortablePanel.Width - ScaleX(10); oPortableWarningText.Height := ScaleY(15); oPortableWarningText.Anchors := [akLeft, akBottom, akRight]; oPortableWarningText.WordWrap := True oPortableWarningText.Font.Color := $007EFF; oPortableWarningText.Font.Style := [fsBold]; oPortableWarningText.Caption := 'Portable installation with Administrator rights may cause unforeseen consequences. Proceed with caution.'; end; end; oSystemChoice.Checked := bIsSystemMode; oUserChoice.Checked := bIsUserMode; oPortableChoice.Checked := bIsPortableMode; Result := oPage; end;