diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index a0d9963..6b73caa 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -11,6 +11,8 @@ #warning "Automatic updater debugging is enabled" #endif +using System.ComponentModel; +using System.Data; using System.Windows; using System.Windows.Forms; using System.Windows.Shell; @@ -337,7 +339,12 @@ namespace Bloxstrap WorkingDirectory = AppData.Directory }; - if (_launchMode == LaunchMode.StudioAuth) + if (_launchMode == LaunchMode.Player && ShouldRunAsAdmin()) + { + startInfo.Verb = "runas"; + startInfo.UseShellExecute = true; + } + else if (_launchMode == LaunchMode.StudioAuth) { Process.Start(startInfo); return; @@ -372,6 +379,11 @@ namespace Bloxstrap using var process = Process.Start(startInfo)!; _appPid = process.Id; } + catch (Win32Exception ex) when (ex.NativeErrorCode == 1223) + { + // 1223 = ERROR_CANCELLED, gets thrown if a UAC prompt is cancelled + return; + } catch (Exception) { // attempt a reinstall on next launch @@ -456,6 +468,24 @@ namespace Bloxstrap Thread.Sleep(1000); } + private bool ShouldRunAsAdmin() + { + foreach (var root in WindowsRegistry.Roots) + { + using var key = root.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"); + + if (key is null) + continue; + + string? flags = (string?)key.GetValue(AppData.ExecutablePath); + + if (flags is not null && flags.Contains("RUNASADMIN", StringComparison.OrdinalIgnoreCase)) + return true; + } + + return false; + } + public void Cancel() { const string LOG_IDENT = "Bootstrapper::Cancel"; diff --git a/Bloxstrap/Utility/WindowsRegistry.cs b/Bloxstrap/Utility/WindowsRegistry.cs index 23ca712..c13cd65 100644 --- a/Bloxstrap/Utility/WindowsRegistry.cs +++ b/Bloxstrap/Utility/WindowsRegistry.cs @@ -5,6 +5,8 @@ namespace Bloxstrap.Utility static class WindowsRegistry { private const string RobloxPlaceKey = "Roblox.Place"; + + public static readonly List Roots = new() { Registry.CurrentUser, Registry.LocalMachine }; public static void RegisterProtocol(string key, string name, string handler, string handlerParam = "%1") {