From 09fc1dc0313d629525deb6d4134d75bf3aae2b50 Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Fri, 2 Feb 2024 15:04:21 +0000 Subject: [PATCH 1/9] create launchsettings --- Bloxstrap/App.xaml.cs | 245 ++++++------------ Bloxstrap/Bootstrapper.cs | 10 +- Bloxstrap/InstallChecker.cs | 6 +- Bloxstrap/LaunchSettings.cs | 181 +++++++++++++ .../Models/Attributes/LaunchFlagAttribute.cs | 24 ++ Bloxstrap/UI/Frontend.cs | 2 +- 6 files changed, 290 insertions(+), 178 deletions(-) create mode 100644 Bloxstrap/LaunchSettings.cs create mode 100644 Bloxstrap/Models/Attributes/LaunchFlagAttribute.cs diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index 8421d8d..b9a9c29 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -27,12 +27,7 @@ namespace Bloxstrap public static bool IsSetupComplete { get; set; } = true; public static bool IsFirstRun { get; set; } = true; - public static bool IsQuiet { get; private set; } = false; - public static bool IsUninstall { get; private set; } = false; - public static bool IsNoLaunch { get; private set; } = false; - public static bool IsUpgrade { get; private set; } = false; - public static bool IsMenuLaunch { get; private set; } = false; - public static string[] LaunchArgs { get; private set; } = null!; + public static LaunchSettings LaunchSettings { get; private set; } = null!; public static BuildMetadataAttribute BuildMetadata = Assembly.GetExecutingAssembly().GetCustomAttribute()!; public static string Version = Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2]; @@ -103,6 +98,15 @@ namespace Bloxstrap #endif } + private void StartupFinished() + { + const string LOG_IDENT = "App::StartupFinished"; + + Logger.WriteLine(LOG_IDENT, "Successfully reached end of main thread. Terminating..."); + + Terminate(); + } + protected override void OnStartup(StartupEventArgs e) { const string LOG_IDENT = "App::OnStartup"; @@ -122,47 +126,10 @@ namespace Bloxstrap // see https://aka.ms/applicationconfiguration. ApplicationConfiguration.Initialize(); - LaunchArgs = e.Args; - -#if DEBUG - Logger.WriteLine(LOG_IDENT, $"Arguments: {string.Join(' ', LaunchArgs)}"); -#endif + LaunchSettings = new LaunchSettings(e.Args); HttpClient.Timeout = TimeSpan.FromSeconds(30); HttpClient.DefaultRequestHeaders.Add("User-Agent", ProjectRepository); - - if (LaunchArgs.Length > 0) - { - if (Array.IndexOf(LaunchArgs, "-preferences") != -1 || Array.IndexOf(LaunchArgs, "-menu") != -1) - { - Logger.WriteLine(LOG_IDENT, "Started with IsMenuLaunch flag"); - IsMenuLaunch = true; - } - - if (Array.IndexOf(LaunchArgs, "-quiet") != -1) - { - Logger.WriteLine(LOG_IDENT, "Started with IsQuiet flag"); - IsQuiet = true; - } - - if (Array.IndexOf(LaunchArgs, "-uninstall") != -1) - { - Logger.WriteLine(LOG_IDENT, "Started with IsUninstall flag"); - IsUninstall = true; - } - - if (Array.IndexOf(LaunchArgs, "-nolaunch") != -1) - { - Logger.WriteLine(LOG_IDENT, "Started with IsNoLaunch flag"); - IsNoLaunch = true; - } - - if (Array.IndexOf(LaunchArgs, "-upgrade") != -1) - { - Logger.WriteLine(LOG_IDENT, "Bloxstrap started with IsUpgrade flag"); - IsUpgrade = true; - } - } using (var checker = new InstallChecker()) { @@ -175,7 +142,7 @@ namespace Bloxstrap // just in case the user decides to cancel the install if (!IsFirstRun) { - Logger.Initialize(IsUninstall); + Logger.Initialize(LaunchSettings.IsUninstall); if (!Logger.Initialized) { @@ -188,7 +155,7 @@ namespace Bloxstrap FastFlags.Load(); } - if (!IsUninstall && !IsMenuLaunch) + if (!LaunchSettings.IsUninstall && !LaunchSettings.IsMenuLaunch) NotifyIcon = new(); #if !DEBUG @@ -196,10 +163,7 @@ namespace Bloxstrap InstallChecker.CheckUpgrade(); #endif - string commandLine = ""; - LaunchMode? launchMode = null; - - if (IsMenuLaunch) + if (LaunchSettings.IsMenuLaunch) { Process? menuProcess = Process.GetProcesses().Where(x => x.MainWindowTitle == $"{ProjectName} Menu").FirstOrDefault(); @@ -211,7 +175,7 @@ namespace Bloxstrap } else { - if (Process.GetProcessesByName(ProjectName).Length > 1 && !IsQuiet) + if (Process.GetProcessesByName(ProjectName).Length > 1 && !LaunchSettings.IsQuiet) Frontend.ShowMessageBox( Bloxstrap.Resources.Strings.Menu_AlreadyRunning, MessageBoxImage.Information @@ -219,152 +183,95 @@ namespace Bloxstrap Frontend.ShowMenu(); } - } - else if (LaunchArgs.Length > 0) - { - if (LaunchArgs[0].StartsWith("roblox-player:")) - { - commandLine = ProtocolHandler.ParseUri(LaunchArgs[0]); - launchMode = LaunchMode.Player; - } - else if (LaunchArgs[0].StartsWith("roblox:")) - { - if (Settings.Prop.UseDisableAppPatch) - Frontend.ShowMessageBox( - Bloxstrap.Resources.Strings.Bootstrapper_DeeplinkTempEnabled, - MessageBoxImage.Information - ); - - commandLine = $"--app --deeplink {LaunchArgs[0]}"; - - launchMode = LaunchMode.Player; - } - else if (LaunchArgs[0].StartsWith("roblox-studio:")) - { - commandLine = ProtocolHandler.ParseUri(LaunchArgs[0]); - - if (!commandLine.Contains("-startEvent")) - commandLine += " -startEvent www.roblox.com/robloxQTStudioStartedEvent"; - - launchMode = LaunchMode.Studio; - } - else if (LaunchArgs[0].StartsWith("roblox-studio-auth:")) - { - commandLine = HttpUtility.UrlDecode(LaunchArgs[0]); - - launchMode = LaunchMode.StudioAuth; - } - else if (LaunchArgs[0] == "-ide") - { - launchMode = LaunchMode.Studio; - - if (LaunchArgs.Length >= 2) - commandLine = $"-task EditFile -localPlaceFile \"{LaunchArgs[1]}\""; - } - else - { - commandLine = "--app"; - - launchMode = LaunchMode.Player; - } - } - else - { - commandLine = "--app"; - - launchMode = LaunchMode.Player; + StartupFinished(); + return; } - if (launchMode != null) + if (!IsFirstRun) + ShouldSaveConfigs = true; + + // start bootstrapper and show the bootstrapper modal if we're not running silently + Logger.WriteLine(LOG_IDENT, "Initializing bootstrapper"); + Bootstrapper bootstrapper = new(LaunchSettings.RobloxLaunchArgs, LaunchSettings.RobloxLaunchMode); + IBootstrapperDialog? dialog = null; + + if (!LaunchSettings.IsQuiet) { - if (!IsFirstRun) - ShouldSaveConfigs = true; - - // start bootstrapper and show the bootstrapper modal if we're not running silently - Logger.WriteLine(LOG_IDENT, "Initializing bootstrapper"); - Bootstrapper bootstrapper = new(commandLine, (LaunchMode)launchMode); - IBootstrapperDialog? dialog = null; + Logger.WriteLine(LOG_IDENT, "Initializing bootstrapper dialog"); + dialog = Settings.Prop.BootstrapperStyle.GetNew(); + bootstrapper.Dialog = dialog; + dialog.Bootstrapper = bootstrapper; + } - if (!IsQuiet) + // handle roblox singleton mutex for multi-instance launching + // note we're handling it here in the main thread and NOT in the + // bootstrapper as handling mutexes in async contexts suuuuuucks + + Mutex? singletonMutex = null; + + if (Settings.Prop.MultiInstanceLaunching && LaunchSettings.RobloxLaunchMode == LaunchMode.Player) + { + Logger.WriteLine(LOG_IDENT, "Creating singleton mutex"); + + try { - Logger.WriteLine(LOG_IDENT, "Initializing bootstrapper dialog"); - dialog = Settings.Prop.BootstrapperStyle.GetNew(); - bootstrapper.Dialog = dialog; - dialog.Bootstrapper = bootstrapper; + Mutex.OpenExisting("ROBLOX_singletonMutex"); + Logger.WriteLine(LOG_IDENT, "Warning - singleton mutex already exists!"); } - - // handle roblox singleton mutex for multi-instance launching - // note we're handling it here in the main thread and NOT in the - // bootstrapper as handling mutexes in async contexts suuuuuucks - - Mutex? singletonMutex = null; - - if (Settings.Prop.MultiInstanceLaunching && launchMode == LaunchMode.Player) + catch { - Logger.WriteLine(LOG_IDENT, "Creating singleton mutex"); - - try - { - Mutex.OpenExisting("ROBLOX_singletonMutex"); - Logger.WriteLine(LOG_IDENT, "Warning - singleton mutex already exists!"); - } - catch - { - // create the singleton mutex before the game client does - singletonMutex = new Mutex(true, "ROBLOX_singletonMutex"); - } + // create the singleton mutex before the game client does + singletonMutex = new Mutex(true, "ROBLOX_singletonMutex"); } + } - Task bootstrapperTask = Task.Run(async () => await bootstrapper.Run()).ContinueWith(t => - { - Logger.WriteLine(LOG_IDENT, "Bootstrapper task has finished"); + Task bootstrapperTask = Task.Run(async () => await bootstrapper.Run()).ContinueWith(t => + { + Logger.WriteLine(LOG_IDENT, "Bootstrapper task has finished"); - // notifyicon is blocking main thread, must be disposed here - NotifyIcon?.Dispose(); + // notifyicon is blocking main thread, must be disposed here + NotifyIcon?.Dispose(); - if (t.IsFaulted) - Logger.WriteLine(LOG_IDENT, "An exception occurred when running the bootstrapper"); + if (t.IsFaulted) + Logger.WriteLine(LOG_IDENT, "An exception occurred when running the bootstrapper"); - if (t.Exception is null) - return; + if (t.Exception is null) + return; - Logger.WriteException(LOG_IDENT, t.Exception); + Logger.WriteException(LOG_IDENT, t.Exception); - Exception exception = t.Exception; + Exception exception = t.Exception; #if !DEBUG - if (t.Exception.GetType().ToString() == "System.AggregateException") + if (t.Exception.GetType().ToString() == "System.AggregateException") exception = t.Exception.InnerException!; #endif - FinalizeExceptionHandling(exception, false); - }); + FinalizeExceptionHandling(exception, false); + }); - // this ordering is very important as all wpf windows are shown as modal dialogs, mess it up and you'll end up blocking input to one of them - dialog?.ShowBootstrapper(); + // this ordering is very important as all wpf windows are shown as modal dialogs, mess it up and you'll end up blocking input to one of them + dialog?.ShowBootstrapper(); - if (!IsNoLaunch && Settings.Prop.EnableActivityTracking) - NotifyIcon?.InitializeContextMenu(); + if (!LaunchSettings.IsNoLaunch && Settings.Prop.EnableActivityTracking) + NotifyIcon?.InitializeContextMenu(); - Logger.WriteLine(LOG_IDENT, "Waiting for bootstrapper task to finish"); + Logger.WriteLine(LOG_IDENT, "Waiting for bootstrapper task to finish"); - bootstrapperTask.Wait(); + bootstrapperTask.Wait(); - if (singletonMutex is not null) - { - Logger.WriteLine(LOG_IDENT, "We have singleton mutex ownership! Running in background until all Roblox processes are closed"); + if (singletonMutex is not null) + { + Logger.WriteLine(LOG_IDENT, "We have singleton mutex ownership! Running in background until all Roblox processes are closed"); - // we've got ownership of the roblox singleton mutex! - // if we stop running, everything will screw up once any more roblox instances launched - while (Process.GetProcessesByName("RobloxPlayerBeta").Any()) - Thread.Sleep(5000); - } + // we've got ownership of the roblox singleton mutex! + // if we stop running, everything will screw up once any more roblox instances launched + while (Process.GetProcessesByName("RobloxPlayerBeta").Any()) + Thread.Sleep(5000); } - Logger.WriteLine(LOG_IDENT, "Successfully reached end of main thread. Terminating..."); - - Terminate(); + StartupFinished(); } } } diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index bcfbf8b..6214e2e 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -123,7 +123,7 @@ namespace Bloxstrap App.Logger.WriteLine(LOG_IDENT, "Running bootstrapper"); - if (App.IsUninstall) + if (App.LaunchSettings.IsUninstall) { Uninstall(); return; @@ -226,9 +226,9 @@ namespace Bloxstrap await mutex.ReleaseAsync(); - if (App.IsFirstRun && App.IsNoLaunch) + if (App.IsFirstRun && App.LaunchSettings.IsNoLaunch) Dialog?.ShowSuccess(Resources.Strings.Bootstrapper_SuccessfullyInstalled); - else if (!App.IsNoLaunch && !_cancelFired) + else if (!App.LaunchSettings.IsNoLaunch && !_cancelFired) await StartRoblox(); } @@ -302,7 +302,7 @@ namespace Bloxstrap MessageBoxImage.Error ); - if (!App.IsQuiet) + if (!App.LaunchSettings.IsQuiet) Utilities.ShellExecute("https://support.microsoft.com/en-us/topic/media-feature-pack-list-for-windows-n-editions-c1c6fffa-d052-8338-7a79-a4bb980a700a"); Dialog?.CloseBootstrapper(); @@ -655,7 +655,7 @@ namespace Bloxstrap FileName = downloadLocation, }; - foreach (string arg in App.LaunchArgs) + foreach (string arg in App.LaunchSettings.Args) startInfo.ArgumentList.Add(arg); App.Settings.Save(); diff --git a/Bloxstrap/InstallChecker.cs b/Bloxstrap/InstallChecker.cs index 2524928..d3237d2 100644 --- a/Bloxstrap/InstallChecker.cs +++ b/Bloxstrap/InstallChecker.cs @@ -124,7 +124,7 @@ namespace Bloxstrap App.BaseDirectory = Path.Combine(Paths.LocalAppData, App.ProjectName); App.Logger.Initialize(true); - if (App.IsQuiet) + if (App.LaunchSettings.IsQuiet) return; App.IsSetupComplete = false; @@ -159,7 +159,7 @@ namespace Bloxstrap MessageBoxResult result; // silently upgrade version if the command line flag is set or if we're launching from an auto update - if (App.IsUpgrade || isAutoUpgrade) + if (App.LaunchSettings.IsUpgrade || isAutoUpgrade) { result = MessageBoxResult.Yes; } @@ -238,7 +238,7 @@ namespace Bloxstrap (_, _) => Utilities.ShellExecute($"https://github.com/{App.ProjectRepository}/releases/tag/v{currentVersionInfo.ProductVersion}") ); } - else if (!App.IsQuiet) + else if (!App.LaunchSettings.IsQuiet) { Frontend.ShowMessageBox( string.Format(Resources.Strings.InstallChecker_Updated, currentVersionInfo.ProductVersion), diff --git a/Bloxstrap/LaunchSettings.cs b/Bloxstrap/LaunchSettings.cs new file mode 100644 index 0000000..16765fa --- /dev/null +++ b/Bloxstrap/LaunchSettings.cs @@ -0,0 +1,181 @@ +using Bloxstrap.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using System.Web; +using System.Windows; + +namespace Bloxstrap +{ + public class LaunchSettings + { + [LaunchFlag(new[] { "-preferences", "-menu" })] + public bool IsMenuLaunch { get; private set; } = false; + + [LaunchFlag("-quiet")] + public bool IsQuiet { get; private set; } = false; + + [LaunchFlag("-uninstall")] + public bool IsUninstall { get; private set; } = false; + + [LaunchFlag("-nolaunch")] + public bool IsNoLaunch { get; private set; } = false; + + [LaunchFlag("-upgrade")] + public bool IsUpgrade { get; private set; } = false; + + public LaunchMode RobloxLaunchMode { get; private set; } = LaunchMode.Player; + + public string RobloxLaunchArgs { get; private set; } = "--app"; + + /// + /// Original launch arguments + /// + public string[] Args { get; private set; } + + private Dictionary? _flagMap; + + // pizzaboxer wanted this + private void ParseLaunchFlagProps() + { + _flagMap = new Dictionary(); + + foreach (var prop in typeof(LaunchSettings).GetProperties()) + { + var attr = prop.GetCustomAttribute(); + + if (attr == null) + continue; + + if (!string.IsNullOrEmpty(attr.Name)) + { + _flagMap[attr.Name] = prop; + } + else + { + foreach (var name in attr.Names!) + _flagMap[name] = prop; + } + } + } + + private void ParseFlag(string arg) + { + const string LOG_IDENT = "LaunchSettings::ParseFlag"; + + arg = arg.ToLowerInvariant(); + + if (_flagMap!.ContainsKey(arg)) + { + var prop = _flagMap[arg]; + prop.SetValue(this, true); + App.Logger.WriteLine(LOG_IDENT, $"Started with {prop.Name} flag"); + } + } + + private void ParseRoblox(string arg, ref int i) + { + if (arg.StartsWith("roblox-player:")) + { + RobloxLaunchArgs = ProtocolHandler.ParseUri(arg); + + RobloxLaunchMode = LaunchMode.Player; + } + else if (arg.StartsWith("roblox:")) + { + if (App.Settings.Prop.UseDisableAppPatch) + Frontend.ShowMessageBox( + Resources.Strings.Bootstrapper_DeeplinkTempEnabled, + MessageBoxImage.Information + ); + + RobloxLaunchArgs = $"--app --deeplink {arg}"; + + RobloxLaunchMode = LaunchMode.Player; + } + else if (arg.StartsWith("roblox-studio:")) + { + RobloxLaunchArgs = ProtocolHandler.ParseUri(arg); + + if (!RobloxLaunchArgs.Contains("-startEvent")) + RobloxLaunchArgs += " -startEvent www.roblox.com/robloxQTStudioStartedEvent"; + + RobloxLaunchMode = LaunchMode.Studio; + } + else if (arg.StartsWith("roblox-studio-auth:")) + { + RobloxLaunchArgs = HttpUtility.UrlDecode(arg); + + RobloxLaunchMode = LaunchMode.StudioAuth; + } + else if (arg == "-ide") + { + RobloxLaunchMode = LaunchMode.Studio; + + if (Args.Length >= 2) + { + string pathArg = Args[i + 1]; + + if (pathArg.StartsWith('-')) + return; // likely a launch flag, ignore it. + + i++; // path arg + RobloxLaunchArgs = $"-task EditFile -localPlaceFile \"{pathArg}\""; + } + } + } + + private void Parse() + { + const string LOG_IDENT = "LaunchSettings::Parse"; + + App.Logger.WriteLine(LOG_IDENT, "Parsing launch arguments"); + +#if DEBUG + App.Logger.WriteLine(LOG_IDENT, $"Launch arguments: {string.Join(' ', Args)}"); +#endif + + if (Args.Length == 0) + { + App.Logger.WriteLine(LOG_IDENT, "No launch arguments to parse"); + return; + } + + int idx = 0; + string firstArg = Args[0]; + + // check & handle roblox arg + if (!firstArg.StartsWith('-') || firstArg == "-ide") + { + ParseRoblox(firstArg, ref idx); + idx++; // roblox arg + } + + // check if there are any launch flags + if (idx > Args.Length - 1) + return; + + App.Logger.WriteLine(LOG_IDENT, "Parsing launch flags"); + + // map out launch flags + ParseLaunchFlagProps(); + + // parse any launch flags + for (int i = idx; i < Args.Length; i++) + ParseFlag(Args[i]); + + // cleanup flag map + _flagMap!.Clear(); + _flagMap = null; + } + + public LaunchSettings(string[] args) + { + Args = args; + Parse(); + } + } +} diff --git a/Bloxstrap/Models/Attributes/LaunchFlagAttribute.cs b/Bloxstrap/Models/Attributes/LaunchFlagAttribute.cs new file mode 100644 index 0000000..60c3886 --- /dev/null +++ b/Bloxstrap/Models/Attributes/LaunchFlagAttribute.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bloxstrap.Models.Attributes +{ + public class LaunchFlagAttribute : Attribute + { + public string? Name { get; private set; } + public string[]? Names { get; private set; } + + public LaunchFlagAttribute(string name) + { + Name = name; + } + + public LaunchFlagAttribute(string[] names) + { + Names = names; + } + } +} diff --git a/Bloxstrap/UI/Frontend.cs b/Bloxstrap/UI/Frontend.cs index bce2d8a..e66f8a2 100644 --- a/Bloxstrap/UI/Frontend.cs +++ b/Bloxstrap/UI/Frontend.cs @@ -12,7 +12,7 @@ namespace Bloxstrap.UI public static MessageBoxResult ShowMessageBox(string message, MessageBoxImage icon = MessageBoxImage.None, MessageBoxButton buttons = MessageBoxButton.OK, MessageBoxResult defaultResult = MessageBoxResult.None) { - if (App.IsQuiet) + if (App.LaunchSettings.IsQuiet) return defaultResult; switch (App.Settings.Prop.BootstrapperStyle) From b5114c8e7337796a11fe95b2a8872e88e2bb5a18 Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Fri, 2 Feb 2024 15:09:35 +0000 Subject: [PATCH 2/9] fix release builds --- Bloxstrap/App.xaml.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index b9a9c29..f6e7072 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -91,7 +91,7 @@ namespace Bloxstrap _showingExceptionDialog = true; - if (!IsQuiet) + if (!LaunchSettings.IsQuiet) Frontend.ShowExceptionDialog(exception); Terminate(ErrorCode.ERROR_INSTALL_FAILURE); @@ -159,7 +159,7 @@ namespace Bloxstrap NotifyIcon = new(); #if !DEBUG - if (!IsUninstall && !IsFirstRun) + if (!LaunchSettings.IsUninstall && !IsFirstRun) InstallChecker.CheckUpgrade(); #endif From 635d4492aa590b93939e0311c083ad184cfa4a6d Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Sat, 3 Feb 2024 13:24:28 +0000 Subject: [PATCH 3/9] use mutexes --- Bloxstrap/App.xaml.cs | 15 +++++++++------ Bloxstrap/InterProcessLock.cs | 30 ++++++++++++++++++++++++++++++ Bloxstrap/NativeMethods.txt | 3 +-- 3 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 Bloxstrap/InterProcessLock.cs diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index f6e7072..ad3b761 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -163,19 +163,22 @@ namespace Bloxstrap InstallChecker.CheckUpgrade(); #endif + using InterProcessLock processLock = new InterProcessLock("Process", TimeSpan.FromMilliseconds(100)); + if (LaunchSettings.IsMenuLaunch) { - Process? menuProcess = Process.GetProcesses().Where(x => x.MainWindowTitle == $"{ProjectName} Menu").FirstOrDefault(); + using InterProcessLock menuLock = new InterProcessLock("Menu", TimeSpan.FromMilliseconds(100)); - if (menuProcess is not null) + if (!menuLock.IsAcquired) { - var handle = menuProcess.MainWindowHandle; - Logger.WriteLine(LOG_IDENT, $"Found an already existing menu window with handle {handle}"); - PInvoke.SetForegroundWindow((HWND)handle); + Frontend.ShowMessageBox( + "The Bloxstrap menu is already open.", + MessageBoxImage.Error + ); } else { - if (Process.GetProcessesByName(ProjectName).Length > 1 && !LaunchSettings.IsQuiet) + if (!processLock.IsAcquired && !LaunchSettings.IsQuiet) Frontend.ShowMessageBox( Bloxstrap.Resources.Strings.Menu_AlreadyRunning, MessageBoxImage.Information diff --git a/Bloxstrap/InterProcessLock.cs b/Bloxstrap/InterProcessLock.cs new file mode 100644 index 0000000..e1938e8 --- /dev/null +++ b/Bloxstrap/InterProcessLock.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bloxstrap +{ + public class InterProcessLock : IDisposable + { + public Mutex Mutex { get; private set; } + + public bool IsAcquired { get; private set; } + + public InterProcessLock(string name, TimeSpan timeout) + { + Mutex = new Mutex(false, "Bloxstrap-" + name); + IsAcquired = Mutex.WaitOne(timeout); + } + + public void Dispose() + { + if (IsAcquired) + { + Mutex.ReleaseMutex(); + IsAcquired = false; + } + } + } +} diff --git a/Bloxstrap/NativeMethods.txt b/Bloxstrap/NativeMethods.txt index aaa0b6a..bc49657 100644 --- a/Bloxstrap/NativeMethods.txt +++ b/Bloxstrap/NativeMethods.txt @@ -1,5 +1,4 @@ -SetForegroundWindow -FlashWindow +FlashWindow GetWindowLong SetWindowLong EnumDisplaySettings From d7966f438599a50b7cad1220038df48267b76c98 Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Sat, 3 Feb 2024 13:25:52 +0000 Subject: [PATCH 4/9] add to strings --- Bloxstrap/App.xaml.cs | 2 +- Bloxstrap/Resources/Strings.Designer.cs | 9 +++++++++ Bloxstrap/Resources/Strings.resx | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index ad3b761..e7a8f83 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -172,7 +172,7 @@ namespace Bloxstrap if (!menuLock.IsAcquired) { Frontend.ShowMessageBox( - "The Bloxstrap menu is already open.", + Bloxstrap.Resources.Strings.Menu_MenuAlreadyRunning, MessageBoxImage.Error ); } diff --git a/Bloxstrap/Resources/Strings.Designer.cs b/Bloxstrap/Resources/Strings.Designer.cs index d1ad1f1..2bcf4db 100644 --- a/Bloxstrap/Resources/Strings.Designer.cs +++ b/Bloxstrap/Resources/Strings.Designer.cs @@ -2457,6 +2457,15 @@ namespace Bloxstrap.Resources { } } + /// + /// Looks up a localized string similar to The Bloxstrap menu is already open.. + /// + public static string Menu_MenuAlreadyRunning { + get { + return ResourceManager.GetString("Menu.MenuAlreadyRunning", resourceCulture); + } + } + /// /// Looks up a localized string similar to Manage and apply file mods to the Roblox game client.. /// diff --git a/Bloxstrap/Resources/Strings.resx b/Bloxstrap/Resources/Strings.resx index a8f5b58..331331d 100644 --- a/Bloxstrap/Resources/Strings.resx +++ b/Bloxstrap/Resources/Strings.resx @@ -930,6 +930,9 @@ Selecting 'No' will ignore this warning and continue installation. Integrations + + The Bloxstrap menu is already open. + Manage and apply file mods to the Roblox game client. From ee8890894001a83f05ffa20b855c1831166a321f Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Sun, 4 Feb 2024 14:10:50 +0000 Subject: [PATCH 5/9] add log and quiet check --- Bloxstrap/App.xaml.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index e7a8f83..b27d21a 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -171,10 +171,13 @@ namespace Bloxstrap if (!menuLock.IsAcquired) { - Frontend.ShowMessageBox( - Bloxstrap.Resources.Strings.Menu_MenuAlreadyRunning, - MessageBoxImage.Error - ); + Logger.WriteLine(LOG_IDENT, "Could not acquire menu mutex"); + + if (!LaunchSettings.IsQuiet) + Frontend.ShowMessageBox( + Bloxstrap.Resources.Strings.Menu_MenuAlreadyRunning, + MessageBoxImage.Error + ); } else { From 375738fe7010210d754416d36c74eb0840ee6b5d Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Wed, 7 Feb 2024 15:00:22 +0000 Subject: [PATCH 6/9] Revert "add log and quiet check" This reverts commit ee8890894001a83f05ffa20b855c1831166a321f. --- Bloxstrap/App.xaml.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index b27d21a..e7a8f83 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -171,13 +171,10 @@ namespace Bloxstrap if (!menuLock.IsAcquired) { - Logger.WriteLine(LOG_IDENT, "Could not acquire menu mutex"); - - if (!LaunchSettings.IsQuiet) - Frontend.ShowMessageBox( - Bloxstrap.Resources.Strings.Menu_MenuAlreadyRunning, - MessageBoxImage.Error - ); + Frontend.ShowMessageBox( + Bloxstrap.Resources.Strings.Menu_MenuAlreadyRunning, + MessageBoxImage.Error + ); } else { From 9efa1f01f3716abe7a1c22a3a767e81504921dd1 Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Wed, 7 Feb 2024 15:00:31 +0000 Subject: [PATCH 7/9] Revert "add to strings" This reverts commit d7966f438599a50b7cad1220038df48267b76c98. --- Bloxstrap/App.xaml.cs | 2 +- Bloxstrap/Resources/Strings.Designer.cs | 9 --------- Bloxstrap/Resources/Strings.resx | 3 --- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index e7a8f83..ad3b761 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -172,7 +172,7 @@ namespace Bloxstrap if (!menuLock.IsAcquired) { Frontend.ShowMessageBox( - Bloxstrap.Resources.Strings.Menu_MenuAlreadyRunning, + "The Bloxstrap menu is already open.", MessageBoxImage.Error ); } diff --git a/Bloxstrap/Resources/Strings.Designer.cs b/Bloxstrap/Resources/Strings.Designer.cs index 2bcf4db..d1ad1f1 100644 --- a/Bloxstrap/Resources/Strings.Designer.cs +++ b/Bloxstrap/Resources/Strings.Designer.cs @@ -2457,15 +2457,6 @@ namespace Bloxstrap.Resources { } } - /// - /// Looks up a localized string similar to The Bloxstrap menu is already open.. - /// - public static string Menu_MenuAlreadyRunning { - get { - return ResourceManager.GetString("Menu.MenuAlreadyRunning", resourceCulture); - } - } - /// /// Looks up a localized string similar to Manage and apply file mods to the Roblox game client.. /// diff --git a/Bloxstrap/Resources/Strings.resx b/Bloxstrap/Resources/Strings.resx index 331331d..a8f5b58 100644 --- a/Bloxstrap/Resources/Strings.resx +++ b/Bloxstrap/Resources/Strings.resx @@ -930,9 +930,6 @@ Selecting 'No' will ignore this warning and continue installation. Integrations - - The Bloxstrap menu is already open. - Manage and apply file mods to the Roblox game client. From d3d134ae0d769cf42d0ad5ff1dccfef4b4deaed9 Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Wed, 7 Feb 2024 15:00:38 +0000 Subject: [PATCH 8/9] Revert "use mutexes" This reverts commit 635d4492aa590b93939e0311c083ad184cfa4a6d. --- Bloxstrap/App.xaml.cs | 15 ++++++--------- Bloxstrap/InterProcessLock.cs | 30 ------------------------------ Bloxstrap/NativeMethods.txt | 3 ++- 3 files changed, 8 insertions(+), 40 deletions(-) delete mode 100644 Bloxstrap/InterProcessLock.cs diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index ad3b761..f6e7072 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -163,22 +163,19 @@ namespace Bloxstrap InstallChecker.CheckUpgrade(); #endif - using InterProcessLock processLock = new InterProcessLock("Process", TimeSpan.FromMilliseconds(100)); - if (LaunchSettings.IsMenuLaunch) { - using InterProcessLock menuLock = new InterProcessLock("Menu", TimeSpan.FromMilliseconds(100)); + Process? menuProcess = Process.GetProcesses().Where(x => x.MainWindowTitle == $"{ProjectName} Menu").FirstOrDefault(); - if (!menuLock.IsAcquired) + if (menuProcess is not null) { - Frontend.ShowMessageBox( - "The Bloxstrap menu is already open.", - MessageBoxImage.Error - ); + var handle = menuProcess.MainWindowHandle; + Logger.WriteLine(LOG_IDENT, $"Found an already existing menu window with handle {handle}"); + PInvoke.SetForegroundWindow((HWND)handle); } else { - if (!processLock.IsAcquired && !LaunchSettings.IsQuiet) + if (Process.GetProcessesByName(ProjectName).Length > 1 && !LaunchSettings.IsQuiet) Frontend.ShowMessageBox( Bloxstrap.Resources.Strings.Menu_AlreadyRunning, MessageBoxImage.Information diff --git a/Bloxstrap/InterProcessLock.cs b/Bloxstrap/InterProcessLock.cs deleted file mode 100644 index e1938e8..0000000 --- a/Bloxstrap/InterProcessLock.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Bloxstrap -{ - public class InterProcessLock : IDisposable - { - public Mutex Mutex { get; private set; } - - public bool IsAcquired { get; private set; } - - public InterProcessLock(string name, TimeSpan timeout) - { - Mutex = new Mutex(false, "Bloxstrap-" + name); - IsAcquired = Mutex.WaitOne(timeout); - } - - public void Dispose() - { - if (IsAcquired) - { - Mutex.ReleaseMutex(); - IsAcquired = false; - } - } - } -} diff --git a/Bloxstrap/NativeMethods.txt b/Bloxstrap/NativeMethods.txt index bc49657..aaa0b6a 100644 --- a/Bloxstrap/NativeMethods.txt +++ b/Bloxstrap/NativeMethods.txt @@ -1,4 +1,5 @@ -FlashWindow +SetForegroundWindow +FlashWindow GetWindowLong SetWindowLong EnumDisplaySettings From aa1f2ccf6e119c1b5ec687c1c81646df67a14458 Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Wed, 7 Feb 2024 15:01:23 +0000 Subject: [PATCH 9/9] Create InterProcessLock.cs --- Bloxstrap/InterProcessLock.cs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Bloxstrap/InterProcessLock.cs diff --git a/Bloxstrap/InterProcessLock.cs b/Bloxstrap/InterProcessLock.cs new file mode 100644 index 0000000..e1938e8 --- /dev/null +++ b/Bloxstrap/InterProcessLock.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bloxstrap +{ + public class InterProcessLock : IDisposable + { + public Mutex Mutex { get; private set; } + + public bool IsAcquired { get; private set; } + + public InterProcessLock(string name, TimeSpan timeout) + { + Mutex = new Mutex(false, "Bloxstrap-" + name); + IsAcquired = Mutex.WaitOne(timeout); + } + + public void Dispose() + { + if (IsAcquired) + { + Mutex.ReleaseMutex(); + IsAcquired = false; + } + } + } +}