templates/windows/installer: Add current user installation method

Thanks to the PR by @abcdw (https://github.com/obsproject/obs-studio/pull/4067) we can support 'local user' installations. These will allow end users to install StreamFX without requiring Administrator rights, or learning how to use OBS Studio in portable mode.
This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2022-09-15 04:37:22 +02:00
parent 3ce695bccc
commit 6701263e10

View file

@ -61,6 +61,7 @@ AppendDefaultGroupName=yes
; Other Information ; Other Information
Uninstallable=yes Uninstallable=yes
CreateUninstallRegKey=not IsPortableMode() CreateUninstallRegKey=not IsPortableMode()
ChangesEnvironment=yes
AllowNoIcons=yes AllowNoIcons=yes
LicenseFile="@ISS_SOURCE_DIR@/LICENSE" LicenseFile="@ISS_SOURCE_DIR@/LICENSE"
OutputDir="@ISS_PACKAGE_DIR@" OutputDir="@ISS_PACKAGE_DIR@"
@ -84,9 +85,77 @@ Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
[Code] [Code]
// ------------------------------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------------------------------ //
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
type
WPARAM = UINT_PTR;
LPARAM = INT_PTR;
LRESULT = INT_PTR;
LSTATUS = DWord;
LPCVOID = UINT_PTR;
HKEY = DWord;
PHKEY = UINT_PTR;
const
SMTO_ABORTIFHUNG = 2;
WM_WININICHANGE = $001A;
WM_SETTINGCHANGE = WM_WININICHANGE;
// HKEY_CURRENT_USER = $80000001;
// HKEY_LOCAL_MACHINE = $80000002;
function advapi32_RegSetKeyValue(
hKey: HKEY;
lpSubKey: string;
lpValueName: string;
dwType: DWord;
lpData: string;
dwData: DWord
): LRESULT;
external 'RegSetKeyValue{#AW}@advapi32.dll stdcall';
function SetRegistryKeyValueString(
Root: HKEY;
Key: string;
Name: string;
Value: string
): BOOL;
begin
advapi32_RegSetKeyValue(Root, Key, Name, 2, Value, Length(Value) * 2);
Result := True;
end;
function user32_SendTextMessageTimeout(
hWnd: HWND;
Msg: UINT;
wParam: WPARAM;
lParam: PAnsiChar;
fuFlags: UINT;
uTimeout: UINT;
out lpdwResult: DWORD): LRESULT;
external 'SendMessageTimeoutA@user32.dll stdcall';
procedure RefreshEnvironment();
var var
oPortablePageStaticChoice: TNewRadioButton; S: AnsiString;
oPortablePagePortableChoice: TNewRadioButton; MsgResult: DWORD;
begin
S := 'Environment';
user32_SendTextMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
PAnsiChar(S), SMTO_ABORTIFHUNG, 5000, MsgResult);
end;
// ------------------------------------------------------------------------------------------------------------------ //
var
oModePageSystemChoice: TNewRadioButton;
oModePageUserChoice: TNewRadioButton;
oModePagePortableChoice: TNewRadioButton;
bIsPortableMode: Boolean;
bIsUserMode: Boolean;
bIsSystemMode: Boolean;
// InnoSetup // InnoSetup
procedure InitializeWizard; forward; procedure InitializeWizard; forward;
@ -96,7 +165,15 @@ function GetDefaultDirectory(Value: String): String; forward;
function GetOutputBinaryDir(Value: String): String; forward; function GetOutputBinaryDir(Value: String): String; forward;
function GetOutputDataDir(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? // Which installation mode is selected?
function IsSystemMode(): Boolean; forward;
function IsUserMode(): Boolean; forward;
function IsPortableMode(): Boolean; forward; function IsPortableMode(): Boolean; forward;
// Other Metadata // Other Metadata
@ -106,17 +183,26 @@ function IsUpgrade(): Boolean; forward;
function UninstallOldVersion(): Integer; forward; function UninstallOldVersion(): Integer; forward;
// Mode Page // Mode Page
function CreatePortablePage: TWizardPage; forward; function CreateModePage: TWizardPage; forward;
procedure OnPortablePagePortableChoiceClick(Sender: TObject); forward; procedure OnModePagePortableChoiceClick(Sender: TObject); forward;
procedure OnPortablePageStaticChoiceClick(Sender: TObject); forward; procedure OnModePageSystemChoiceClick(Sender: TObject); forward;
// ------------------------------------------------------------------------------------------------------------------ //
function InitializeSetup(): Boolean;
begin
bIsSystemMode := IsAdmin();
bIsUsermode := not IsAdmin();
bIsPortableMode := False;
Result := True;
end;
// ------------------------------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------------------------------ //
procedure InitializeWizard; procedure InitializeWizard;
var var
oPortablePage: TWizardPage; oModePage: TWizardPage;
begin begin
oPortablePage := CreatePortablePage(); oModePage := CreateModePage();
end; end;
// ------------------------------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------------------------------ //
@ -129,6 +215,8 @@ end;
function PrepareToInstall(var NeedsRestart: Boolean): String; function PrepareToInstall(var NeedsRestart: Boolean): String;
var var
iResultCode: Integer; iResultCode: Integer;
sPluginsPath: String;
sPluginsDataPath: String;
begin begin
// Attempt to remove old version if it exists. // Attempt to remove old version if it exists.
if (IsUpgrade()) then begin if (IsUpgrade()) then begin
@ -138,6 +226,19 @@ begin
// Also ensure that we have the necessary prerequisites installed to run the program. // Also ensure that we have the necessary prerequisites installed to run the program.
ExtractTemporaryFile('msvc-redist-helper.exe'); ExtractTemporaryFile('msvc-redist-helper.exe');
Exec(ExpandConstant('{tmp}\msvc-redist-helper.exe'), '2019', '', SW_HIDE, ewWaitUntilTerminated, iResultCode); 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('{userpf}\obs-studio\plugins\%module%\bin\');
StringChangeEx(sPluginsPath, '\', '/', True);
SetRegistryKeyValueString(HKEY_CURRENT_USER, 'Environment', 'OBS_PLUGINS_PATH', sPluginsPath);
sPluginsDataPath := ExpandConstant('{userpf}\obs-studio\plugins\%module%\data\');
StringChangeEx(sPluginsDataPath, '\', '/', True);
SetRegistryKeyValueString(HKEY_CURRENT_USER, 'Environment', 'OBS_PLUGINS_DATA_PATH', sPluginsDataPath);
RefreshEnvironment();
end;
end; end;
// ------------------------------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------------------------------ //
@ -145,14 +246,25 @@ function GetDefaultDirectory(Value: String): String;
var var
sPath: String; sPath: String;
begin begin
// If a path was given as an argument, use it.
if (Value <> '') then begin
Result := Value;
exit;
end;
// Otherwise, try and figure out where the previous installation of the same type went to. // Otherwise, try and figure out where the previous installation of the same type went to.
if (RegQueryStringValue(HKA64, AppRegistryKey(), 'InstallLocation', sPath)) then begin if (RegQueryStringValue(HKA64, AppRegistryKey(), 'InstallLocation', sPath)) then begin
Result := sPath; Result := sPath;
exit; exit;
end; end;
// Install to ProgramData. // 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@'); Result := ExpandConstant('{commonappdata}\obs-studio\plugins\@PROJECT_NAME@');
end else begin
Result := ExpandConstant('{userpf}\obs-studio\plugins\@PROJECT_NAME@')
end;
exit; exit;
end; end;
@ -162,10 +274,12 @@ function GetOutputBinaryDir(Value: String): String;
var var
sPath: String; sPath: String;
begin begin
if (IsPortableMode()) then begin if (IsSystemMode()) then begin
sPath := ExpandConstant('{app}\obs-plugins\@D_PLATFORM_BITS@bit\');
end else begin
sPath := ExpandConstant('{app}\bin\@D_PLATFORM_BITS@bit\'); 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; end;
Result := sPath; Result := sPath;
end; end;
@ -174,40 +288,86 @@ function GetOutputDataDir(Value: String): String;
var var
sPath: String; sPath: String;
begin begin
if (IsPortableMode()) then begin if (IsSystemMode()) then begin
sPath := ExpandConstant('{app}\data\obs-plugins\@PROJECT_NAME@\');
end else begin
sPath := ExpandConstant('{app}\data\'); 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; end;
Result := sPath; Result := sPath;
end; end;
// ------------------------------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------------------------------ //
function GetUninstallerPath(): String; function GetSystemUninstaller(): String;
var var
sRegistryKey: String; sPath : String;
sUninstallerPath: String;
begin begin
sRegistryKey := AppRegistryKey(); Result := '';
if (RegQueryStringValue(HKLM64, AppRegistryKey(), 'UninstallString', sPath)) then begin
Result := sPath;
end;
end;
RegQueryStringValue(HKLM64, sRegistryKey, 'UninstallString', sUninstallerPath); function IsSystemInstallPresent(): Boolean;
var
sPath : String;
begin
sPath := GetSystemUninstaller();
if (sPath <> '') then begin
Result := True;
end else begin
Result := False;
end;
end;
if (sUninstallerPath = '') then function GetUserUninstaller(): String;
RegQueryStringValue(HKCU64, sRegistryKey, 'UninstallString', sUninstallerPath); var
sPath : String;
begin
Result := '';
if (RegQueryStringValue(HKCU64, AppRegistryKey(), 'UninstallString', sPath)) then begin
Result := sPath;
end;
end;
if (sUninstallerPath = '') then function IsUserInstallPresent(): Boolean;
RegQueryStringValue(HKLM32, sRegistryKey, 'UninstallString', sUninstallerPath); var
sPath : String;
begin
sPath := GetUserUninstaller();
if (sPath <> '') then begin
Result := True;
end else begin
Result := False;
end;
end;
if (sUninstallerPath = '') then function GetUninstallerPath(): String;
RegQueryStringValue(HKCU32, sRegistryKey, 'UninstallString', sUninstallerPath); begin
if (IsSystemMode()) then begin
Result := sUninstallerPath; Result := GetSystemUninstaller();
end else if (IsUserMode()) then begin
Result := GetUserUninstaller();
end else begin
Result := '';
end;
end; end;
// ------------------------------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------------------------------ //
function IsSystemMode(): Boolean;
begin
Result := bIsSystemMode;
end;
function IsUserMode(): Boolean;
begin
Result := bIsUserMode;
end;
function IsPortableMode(): Boolean; function IsPortableMode(): Boolean;
begin begin
Result := oPortablePagePortableChoice.Checked; Result := bIsPortableMode;
end; end;
// ------------------------------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------------------------------ //
@ -241,95 +401,245 @@ begin
end; end;
// ------------------------------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------------------------------ //
procedure OnPortablePagePortableChoiceClick(Sender: TObject); procedure OnModePageSystemChoiceClick(Sender: TObject);
begin begin
oPortablePageStaticChoice.Checked := False; if (not oModePageSystemChoice.Enabled) then begin
oPortablePagePortableChoice.Checked := True; OnModePagePortableChoiceClick(Sender);
end;
procedure OnPortablePageStaticChoiceClick(Sender: TObject);
begin
if (not oPortablePageStaticChoice.Enabled) then begin
OnPortablePagePortableChoiceClick(Sender);
end else begin end else begin
oPortablePageStaticChoice.Checked := True; oModePageSystemChoice.Checked := True;
oPortablePagePortableChoice.Checked := False; oModePageUserChoice.Checked := False;
oModePagePortableChoice.Checked := False;
bIsSystemMode := True;
bIsUserMode := False;
bIsPortableMode := False;
end; end;
end; end;
function CreatePortablePage: TWizardPage; 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;
end;
end;
procedure OnModePagePortableChoiceClick(Sender: TObject);
begin
oModePageSystemChoice.Checked := False;
oModePageUserChoice.Checked := False;
oModePagePortableChoice.Checked := True;
bIsSystemMode := False;
bIsUserMode := False;
bIsPortableMode := True;
end;
function CreateModePage: TWizardPage;
var var
oPage: TWizardPage; oPage: TWizardPage;
oStaticPanel: TPanel; oSystemPanel: TPanel;
oStaticChoice: TNewRadioButton; oSystemChoice: TNewRadioButton;
oStaticText: TLabel; oSystemText: TLabel;
oStaticWarningText: TLabel; oSystemWarningText: TLabel;
oUserPanel: TPanel;
oUserChoice: TNewRadioButton;
oUserText: TLabel;
oUserWarningText: TLabel;
oPortablePanel: TPanel; oPortablePanel: TPanel;
oPortableChoice: TNewRadioButton; oPortableChoice: TNewRadioButton;
oPortableText: TLabel; oPortableText: TLabel;
oPortableWarningText: TLabel;
oFractionalHeight: Integer;
begin begin
// Build a page that asks a user if they want to use Movable or Static installation. // Build a page that asks a user if they want to use Movable or Static installation.
oPage := CreateCustomPage(wpLicense, oPage := CreateCustomPage(wpLicense,
'Installation Type', 'Installation Mode',
'Select how to install StreamFX on your System'); 'Select how to install StreamFX on your System');
oFractionalHeight := ScaleY((oPage.SurfaceHeight - 10) / 3);
oStaticPanel := TPanel.Create(oPage); // System-Wide installation
oStaticPanel.Parent := oPage.Surface; if (True) then begin
oStaticPanel.ParentBackground := False; oSystemPanel := TPanel.Create(oPage);
oStaticPanel.Left := ScaleX(5); oSystemPanel.Parent := oPage.Surface;
oStaticPanel.Top := ScaleY(5); oSystemPanel.ParentBackground := False;
oStaticPanel.Width := oPage.SurfaceWidth - ScaleX(10); oSystemPanel.Left := ScaleX(5);
oStaticPanel.Height := ScaleY(100); oSystemPanel.Top := ScaleY(5);
oStaticPanel.Anchors := [akLeft, akTop, akRight]; oSystemPanel.Width := oPage.SurfaceWidth - ScaleX(10);
oStaticPanel.Color := clWindow; oSystemPanel.Height := oFractionalHeight;
oStaticPanel.BevelKind := bkTile; oSystemPanel.Anchors := [akLeft, akTop, akRight];
oStaticPanel.BevelInner := bvNone; oSystemPanel.Color := clWindow;
oStaticPanel.BevelOuter := bvRaised; oSystemPanel.BevelKind := bkTile;
oStaticPanel.BevelWidth := 1; oSystemPanel.BevelInner := bvNone;
oStaticPanel.OnClick := @OnPortablePageStaticChoiceClick; oSystemPanel.BevelOuter := bvRaised;
oSystemPanel.BevelWidth := 1;
oSystemPanel.OnClick := @OnModePageSystemChoiceClick;
oStaticChoice := TNewRadioButton.Create(oStaticPanel); oSystemChoice := TNewRadioButton.Create(oSystemPanel);
oPortablePageStaticChoice := oStaticChoice; oModePageSystemChoice := oSystemChoice;
oStaticChoice.Parent := oStaticPanel; oSystemChoice.Parent := oSystemPanel;
oStaticChoice.ParentBackground := False; oSystemChoice.ParentBackground := False;
oStaticChoice.Left := ScaleX(5); oSystemChoice.Left := ScaleX(5);
oStaticChoice.Top := ScaleY(5); oSystemChoice.Top := ScaleY(5);
oStaticChoice.Width := oStaticPanel.Width - ScaleX(10); oSystemChoice.Width := oSystemPanel.Width - ScaleX(10);
oStaticChoice.Height := ScaleY(20); oSystemChoice.Height := ScaleY(20);
oStaticChoice.Anchors := [akLeft, akTop, akRight]; oSystemChoice.Anchors := [akLeft, akTop, akRight];
oStaticChoice.Caption := 'Static'; oSystemChoice.Caption := 'All Users';
oStaticChoice.Font.Style := [fsBold]; oSystemChoice.Font.Style := [fsBold];
oStaticChoice.OnClick := @OnPortablePageStaticChoiceClick; oSystemChoice.OnClick := @OnModePageSystemChoiceClick;
oStaticText := TLabel.Create(oStaticPanel); oSystemText := TLabel.Create(oSystemPanel);
oStaticText.Parent := oStaticPanel; oSystemText.Parent := oSystemPanel;
oStaticText.AutoSize := False; oSystemText.AutoSize := False;
oStaticText.Left := ScaleX(5); oSystemText.Left := ScaleX(5);
oStaticText.Top := ScaleY(5) + oStaticChoice.Top + oStaticChoice.Height; oSystemText.Top := ScaleY(5) + oSystemChoice.Top + oSystemChoice.Height;
oStaticText.Width := oStaticPanel.Width - ScaleX(10); oSystemText.Width := oSystemPanel.Width - ScaleX(10);
oStaticText.Height := oStaticPanel.Height - ScaleX(5) - oStaticText.Top; oSystemText.Height := oSystemPanel.Height - ScaleX(5) - oSystemText.Top;
oStaticText.Anchors := [akLeft, akTop, akRight]; oSystemText.Anchors := [akLeft, akTop, akRight];
oStaticText.WordWrap := True oSystemText.WordWrap := True
oStaticText.Caption := 'Install for use in a static version of OBS Studio, with all necessary features to support it.'; 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.';
oStaticText.OnClick := @OnPortablePageStaticChoiceClick; 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 := TPanel.Create(oPage);
oPortablePanel.Parent := oPage.Surface; oPortablePanel.Parent := oPage.Surface;
oPortablePanel.ParentBackground := False; oPortablePanel.ParentBackground := False;
oPortablePanel.Left := ScaleX(5); oPortablePanel.Left := ScaleX(5);
oPortablePanel.Top := ScaleY(5) + oStaticPanel.Top + oStaticPanel.Height; oPortablePanel.Top := ScaleY(5) + oUserPanel.Top + oUserPanel.Height;
oPortablePanel.Width := oPage.SurfaceWidth - ScaleX(10); oPortablePanel.Width := oPage.SurfaceWidth - ScaleX(10);
oPortablePanel.Height := ScaleY(100); oPortablePanel.Height := oFractionalHeight;
oPortablePanel.Anchors := [akLeft, akTop, akRight]; oPortablePanel.Anchors := [akLeft, akTop, akRight];
oPortablePanel.Color := clWindow; oPortablePanel.Color := clWindow;
oPortablePanel.BevelKind := bkTile; oPortablePanel.BevelKind := bkTile;
oPortablePanel.BevelInner := bvNone; oPortablePanel.BevelInner := bvNone;
oPortablePanel.BevelOuter := bvRaised; oPortablePanel.BevelOuter := bvRaised;
oPortablePanel.BevelWidth := 1; oPortablePanel.BevelWidth := 1;
oPortablePanel.OnClick := @OnPortablePagePortableChoiceClick; oPortablePanel.OnClick := @OnModePagePortableChoiceClick;
oPortableChoice := TNewRadioButton.Create(oPortablePanel); oPortableChoice := TNewRadioButton.Create(oPortablePanel);
oPortablePagePortableChoice := oPortableChoice; oModePagePortableChoice := oPortableChoice;
oPortableChoice.Parent := oPortablePanel; oPortableChoice.Parent := oPortablePanel;
oPortableChoice.ParentBackground := False; oPortableChoice.ParentBackground := False;
oPortableChoice.Left := ScaleX(5); oPortableChoice.Left := ScaleX(5);
@ -339,7 +649,7 @@ begin
oPortableChoice.Anchors := [akLeft, akTop, akRight]; oPortableChoice.Anchors := [akLeft, akTop, akRight];
oPortableChoice.Caption := 'Portable'; oPortableChoice.Caption := 'Portable';
oPortableChoice.Font.Style := [fsBold]; oPortableChoice.Font.Style := [fsBold];
oPortableChoice.OnClick := @OnPortablePagePortableChoiceClick; oPortableChoice.OnClick := @OnModePagePortableChoiceClick;
oPortableText := TLabel.Create(oPortablePanel); oPortableText := TLabel.Create(oPortablePanel);
oPortableText.Parent := oPortablePanel; oPortableText.Parent := oPortablePanel;
@ -350,34 +660,29 @@ begin
oPortableText.Height := oPortablePanel.Height - ScaleX(5) - oPortableText.Top; oPortableText.Height := oPortablePanel.Height - ScaleX(5) - oPortableText.Top;
oPortableText.Anchors := [akLeft, akTop, akRight]; oPortableText.Anchors := [akLeft, akTop, akRight];
oPortableText.WordWrap := True oPortableText.WordWrap := True
oPortableText.Caption := 'Install for use in portable or multi-environment scenarios, which require StreamFX to not be tied to the System itself. The uninstaller, automatic updates and other system-dependent features will be unavailable.'; oPortableText.Caption := 'Install for a portable OBS Studio environment.';
oPortableText.OnClick := @OnPortablePagePortableChoiceClick; oPortableText.OnClick := @OnModePagePortableChoiceClick;
if (not IsAdmin()) then begin // Warn about Administrator rights
oStaticWarningText := TLabel.Create(oStaticPanel); if (IsAdmin()) then begin
oStaticWarningText.Parent := oStaticPanel; oPortableWarningText := TLabel.Create(oPortablePanel);
oStaticWarningText.AutoSize := False; oPortableWarningText.Parent := oPortablePanel;
oStaticWarningText.Left := ScaleX(5); oPortableWarningText.AutoSize := False;
oStaticWarningText.Top := oPortablePanel.Height - ScaleY(5) - ScaleY(15); oPortableWarningText.Left := ScaleX(5);
oStaticWarningText.Width := oPortablePanel.Width - ScaleX(10); oPortableWarningText.Top := oPortablePanel.Height - ScaleY(5) - ScaleY(15);
oStaticWarningText.Height := ScaleY(15); oPortableWarningText.Width := oPortablePanel.Width - ScaleX(10);
oStaticWarningText.Anchors := [akLeft, akBottom, akRight]; oPortableWarningText.Height := ScaleY(15);
oStaticWarningText.WordWrap := True oPortableWarningText.Anchors := [akLeft, akBottom, akRight];
oStaticWarningText.Font.Color := clRed; oPortableWarningText.WordWrap := True
oStaticWarningText.Font.Style := [fsBold]; oPortableWarningText.Font.Color := $007EFF;
oStaticWarningText.Caption := 'Please launch the Installer as Administrator for static installations.'; oPortableWarningText.Font.Style := [fsBold];
oPortableWarningText.Caption := 'Portable installation with Administrator rights may cause unforeseen consequences. Proceed with caution.';
oStaticPanel.Enabled := False;
oStaticChoice.Enabled := False;
oStaticText.Enabled := False;
oStaticChoice.Checked := False;
oPortableChoice.Checked := True;
end else begin
oStaticChoice.Checked := True;
oPortableChoice.Checked := False;
end; end;
end;
oSystemChoice.Checked := bIsSystemMode;
oUserChoice.Checked := bIsUserMode;
oPortableChoice.Checked := bIsPortableMode;
Result := oPage; Result := oPage;
end; end;