mirror of
https://github.com/bloxstraplabs/bloxstrap.git
synced 2025-04-21 10:01:27 -07:00
Merge pull request #1230 from bluepilledgreat/feature/app-cleanup
App cleanup
This commit is contained in:
commit
62ae4c3e89
@ -27,12 +27,7 @@ namespace Bloxstrap
|
|||||||
public static bool IsSetupComplete { get; set; } = true;
|
public static bool IsSetupComplete { get; set; } = true;
|
||||||
public static bool IsFirstRun { get; set; } = true;
|
public static bool IsFirstRun { get; set; } = true;
|
||||||
|
|
||||||
public static bool IsQuiet { get; private set; } = false;
|
public static LaunchSettings LaunchSettings { get; private set; } = null!;
|
||||||
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 BuildMetadataAttribute BuildMetadata = Assembly.GetExecutingAssembly().GetCustomAttribute<BuildMetadataAttribute>()!;
|
public static BuildMetadataAttribute BuildMetadata = Assembly.GetExecutingAssembly().GetCustomAttribute<BuildMetadataAttribute>()!;
|
||||||
public static string Version = Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2];
|
public static string Version = Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2];
|
||||||
@ -96,13 +91,22 @@ namespace Bloxstrap
|
|||||||
|
|
||||||
_showingExceptionDialog = true;
|
_showingExceptionDialog = true;
|
||||||
|
|
||||||
if (!IsQuiet)
|
if (!LaunchSettings.IsQuiet)
|
||||||
Frontend.ShowExceptionDialog(exception);
|
Frontend.ShowExceptionDialog(exception);
|
||||||
|
|
||||||
Terminate(ErrorCode.ERROR_INSTALL_FAILURE);
|
Terminate(ErrorCode.ERROR_INSTALL_FAILURE);
|
||||||
#endif
|
#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)
|
protected override void OnStartup(StartupEventArgs e)
|
||||||
{
|
{
|
||||||
const string LOG_IDENT = "App::OnStartup";
|
const string LOG_IDENT = "App::OnStartup";
|
||||||
@ -122,48 +126,11 @@ namespace Bloxstrap
|
|||||||
// see https://aka.ms/applicationconfiguration.
|
// see https://aka.ms/applicationconfiguration.
|
||||||
ApplicationConfiguration.Initialize();
|
ApplicationConfiguration.Initialize();
|
||||||
|
|
||||||
LaunchArgs = e.Args;
|
LaunchSettings = new LaunchSettings(e.Args);
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
Logger.WriteLine(LOG_IDENT, $"Arguments: {string.Join(' ', LaunchArgs)}");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HttpClient.Timeout = TimeSpan.FromSeconds(30);
|
HttpClient.Timeout = TimeSpan.FromSeconds(30);
|
||||||
HttpClient.DefaultRequestHeaders.Add("User-Agent", ProjectRepository);
|
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())
|
using (var checker = new InstallChecker())
|
||||||
{
|
{
|
||||||
checker.Check();
|
checker.Check();
|
||||||
@ -175,7 +142,7 @@ namespace Bloxstrap
|
|||||||
// just in case the user decides to cancel the install
|
// just in case the user decides to cancel the install
|
||||||
if (!IsFirstRun)
|
if (!IsFirstRun)
|
||||||
{
|
{
|
||||||
Logger.Initialize(IsUninstall);
|
Logger.Initialize(LaunchSettings.IsUninstall);
|
||||||
|
|
||||||
if (!Logger.Initialized)
|
if (!Logger.Initialized)
|
||||||
{
|
{
|
||||||
@ -188,18 +155,15 @@ namespace Bloxstrap
|
|||||||
FastFlags.Load();
|
FastFlags.Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsUninstall && !IsMenuLaunch)
|
if (!LaunchSettings.IsUninstall && !LaunchSettings.IsMenuLaunch)
|
||||||
NotifyIcon = new();
|
NotifyIcon = new();
|
||||||
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if (!IsUninstall && !IsFirstRun)
|
if (!LaunchSettings.IsUninstall && !IsFirstRun)
|
||||||
InstallChecker.CheckUpgrade();
|
InstallChecker.CheckUpgrade();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
string commandLine = "";
|
if (LaunchSettings.IsMenuLaunch)
|
||||||
LaunchMode? launchMode = null;
|
|
||||||
|
|
||||||
if (IsMenuLaunch)
|
|
||||||
{
|
{
|
||||||
Process? menuProcess = Process.GetProcesses().Where(x => x.MainWindowTitle == $"{ProjectName} Menu").FirstOrDefault();
|
Process? menuProcess = Process.GetProcesses().Where(x => x.MainWindowTitle == $"{ProjectName} Menu").FirstOrDefault();
|
||||||
|
|
||||||
@ -211,7 +175,7 @@ namespace Bloxstrap
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Process.GetProcessesByName(ProjectName).Length > 1 && !IsQuiet)
|
if (Process.GetProcessesByName(ProjectName).Length > 1 && !LaunchSettings.IsQuiet)
|
||||||
Frontend.ShowMessageBox(
|
Frontend.ShowMessageBox(
|
||||||
Bloxstrap.Resources.Strings.Menu_AlreadyRunning,
|
Bloxstrap.Resources.Strings.Menu_AlreadyRunning,
|
||||||
MessageBoxImage.Information
|
MessageBoxImage.Information
|
||||||
@ -219,152 +183,95 @@ namespace Bloxstrap
|
|||||||
|
|
||||||
Frontend.ShowMenu();
|
Frontend.ShowMenu();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (LaunchArgs.Length > 0)
|
|
||||||
{
|
|
||||||
if (LaunchArgs[0].StartsWith("roblox-player:"))
|
|
||||||
{
|
|
||||||
commandLine = ProtocolHandler.ParseUri(LaunchArgs[0]);
|
|
||||||
|
|
||||||
launchMode = LaunchMode.Player;
|
StartupFinished();
|
||||||
}
|
return;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
Logger.WriteLine(LOG_IDENT, "Initializing bootstrapper dialog");
|
||||||
ShouldSaveConfigs = true;
|
dialog = Settings.Prop.BootstrapperStyle.GetNew();
|
||||||
|
bootstrapper.Dialog = dialog;
|
||||||
|
dialog.Bootstrapper = bootstrapper;
|
||||||
|
}
|
||||||
|
|
||||||
// start bootstrapper and show the bootstrapper modal if we're not running silently
|
// handle roblox singleton mutex for multi-instance launching
|
||||||
Logger.WriteLine(LOG_IDENT, "Initializing bootstrapper");
|
// note we're handling it here in the main thread and NOT in the
|
||||||
Bootstrapper bootstrapper = new(commandLine, (LaunchMode)launchMode);
|
// bootstrapper as handling mutexes in async contexts suuuuuucks
|
||||||
IBootstrapperDialog? dialog = null;
|
|
||||||
|
|
||||||
if (!IsQuiet)
|
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");
|
Mutex.OpenExisting("ROBLOX_singletonMutex");
|
||||||
dialog = Settings.Prop.BootstrapperStyle.GetNew();
|
Logger.WriteLine(LOG_IDENT, "Warning - singleton mutex already exists!");
|
||||||
bootstrapper.Dialog = dialog;
|
|
||||||
dialog.Bootstrapper = bootstrapper;
|
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
Logger.WriteLine(LOG_IDENT, "Creating singleton mutex");
|
// create the singleton mutex before the game client does
|
||||||
|
singletonMutex = new Mutex(true, "ROBLOX_singletonMutex");
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Task bootstrapperTask = Task.Run(async () => await bootstrapper.Run()).ContinueWith(t =>
|
Task bootstrapperTask = Task.Run(async () => await bootstrapper.Run()).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
Logger.WriteLine(LOG_IDENT, "Bootstrapper task has finished");
|
Logger.WriteLine(LOG_IDENT, "Bootstrapper task has finished");
|
||||||
|
|
||||||
// notifyicon is blocking main thread, must be disposed here
|
// notifyicon is blocking main thread, must be disposed here
|
||||||
NotifyIcon?.Dispose();
|
NotifyIcon?.Dispose();
|
||||||
|
|
||||||
if (t.IsFaulted)
|
if (t.IsFaulted)
|
||||||
Logger.WriteLine(LOG_IDENT, "An exception occurred when running the bootstrapper");
|
Logger.WriteLine(LOG_IDENT, "An exception occurred when running the bootstrapper");
|
||||||
|
|
||||||
if (t.Exception is null)
|
if (t.Exception is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Logger.WriteException(LOG_IDENT, t.Exception);
|
Logger.WriteException(LOG_IDENT, t.Exception);
|
||||||
|
|
||||||
Exception exception = t.Exception;
|
Exception exception = t.Exception;
|
||||||
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if (t.Exception.GetType().ToString() == "System.AggregateException")
|
if (t.Exception.GetType().ToString() == "System.AggregateException")
|
||||||
exception = t.Exception.InnerException!;
|
exception = t.Exception.InnerException!;
|
||||||
#endif
|
#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
|
// 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();
|
dialog?.ShowBootstrapper();
|
||||||
|
|
||||||
if (!IsNoLaunch && Settings.Prop.EnableActivityTracking)
|
if (!LaunchSettings.IsNoLaunch && Settings.Prop.EnableActivityTracking)
|
||||||
NotifyIcon?.InitializeContextMenu();
|
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)
|
if (singletonMutex is not null)
|
||||||
{
|
{
|
||||||
Logger.WriteLine(LOG_IDENT, "We have singleton mutex ownership! Running in background until all Roblox processes are closed");
|
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!
|
// we've got ownership of the roblox singleton mutex!
|
||||||
// if we stop running, everything will screw up once any more roblox instances launched
|
// if we stop running, everything will screw up once any more roblox instances launched
|
||||||
while (Process.GetProcessesByName("RobloxPlayerBeta").Any())
|
while (Process.GetProcessesByName("RobloxPlayerBeta").Any())
|
||||||
Thread.Sleep(5000);
|
Thread.Sleep(5000);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.WriteLine(LOG_IDENT, "Successfully reached end of main thread. Terminating...");
|
StartupFinished();
|
||||||
|
|
||||||
Terminate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ namespace Bloxstrap
|
|||||||
|
|
||||||
App.Logger.WriteLine(LOG_IDENT, "Running bootstrapper");
|
App.Logger.WriteLine(LOG_IDENT, "Running bootstrapper");
|
||||||
|
|
||||||
if (App.IsUninstall)
|
if (App.LaunchSettings.IsUninstall)
|
||||||
{
|
{
|
||||||
Uninstall();
|
Uninstall();
|
||||||
return;
|
return;
|
||||||
@ -226,9 +226,9 @@ namespace Bloxstrap
|
|||||||
|
|
||||||
await mutex.ReleaseAsync();
|
await mutex.ReleaseAsync();
|
||||||
|
|
||||||
if (App.IsFirstRun && App.IsNoLaunch)
|
if (App.IsFirstRun && App.LaunchSettings.IsNoLaunch)
|
||||||
Dialog?.ShowSuccess(Resources.Strings.Bootstrapper_SuccessfullyInstalled);
|
Dialog?.ShowSuccess(Resources.Strings.Bootstrapper_SuccessfullyInstalled);
|
||||||
else if (!App.IsNoLaunch && !_cancelFired)
|
else if (!App.LaunchSettings.IsNoLaunch && !_cancelFired)
|
||||||
await StartRoblox();
|
await StartRoblox();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +302,7 @@ namespace Bloxstrap
|
|||||||
MessageBoxImage.Error
|
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");
|
Utilities.ShellExecute("https://support.microsoft.com/en-us/topic/media-feature-pack-list-for-windows-n-editions-c1c6fffa-d052-8338-7a79-a4bb980a700a");
|
||||||
|
|
||||||
Dialog?.CloseBootstrapper();
|
Dialog?.CloseBootstrapper();
|
||||||
@ -655,7 +655,7 @@ namespace Bloxstrap
|
|||||||
FileName = downloadLocation,
|
FileName = downloadLocation,
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (string arg in App.LaunchArgs)
|
foreach (string arg in App.LaunchSettings.Args)
|
||||||
startInfo.ArgumentList.Add(arg);
|
startInfo.ArgumentList.Add(arg);
|
||||||
|
|
||||||
App.Settings.Save();
|
App.Settings.Save();
|
||||||
|
@ -124,7 +124,7 @@ namespace Bloxstrap
|
|||||||
App.BaseDirectory = Path.Combine(Paths.LocalAppData, App.ProjectName);
|
App.BaseDirectory = Path.Combine(Paths.LocalAppData, App.ProjectName);
|
||||||
App.Logger.Initialize(true);
|
App.Logger.Initialize(true);
|
||||||
|
|
||||||
if (App.IsQuiet)
|
if (App.LaunchSettings.IsQuiet)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
App.IsSetupComplete = false;
|
App.IsSetupComplete = false;
|
||||||
@ -159,7 +159,7 @@ namespace Bloxstrap
|
|||||||
MessageBoxResult result;
|
MessageBoxResult result;
|
||||||
|
|
||||||
// silently upgrade version if the command line flag is set or if we're launching from an auto update
|
// 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;
|
result = MessageBoxResult.Yes;
|
||||||
}
|
}
|
||||||
@ -238,7 +238,7 @@ namespace Bloxstrap
|
|||||||
(_, _) => Utilities.ShellExecute($"https://github.com/{App.ProjectRepository}/releases/tag/v{currentVersionInfo.ProductVersion}")
|
(_, _) => Utilities.ShellExecute($"https://github.com/{App.ProjectRepository}/releases/tag/v{currentVersionInfo.ProductVersion}")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (!App.IsQuiet)
|
else if (!App.LaunchSettings.IsQuiet)
|
||||||
{
|
{
|
||||||
Frontend.ShowMessageBox(
|
Frontend.ShowMessageBox(
|
||||||
string.Format(Resources.Strings.InstallChecker_Updated, currentVersionInfo.ProductVersion),
|
string.Format(Resources.Strings.InstallChecker_Updated, currentVersionInfo.ProductVersion),
|
||||||
|
30
Bloxstrap/InterProcessLock.cs
Normal file
30
Bloxstrap/InterProcessLock.cs
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
181
Bloxstrap/LaunchSettings.cs
Normal file
181
Bloxstrap/LaunchSettings.cs
Normal file
@ -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";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Original launch arguments
|
||||||
|
/// </summary>
|
||||||
|
public string[] Args { get; private set; }
|
||||||
|
|
||||||
|
private Dictionary<string, PropertyInfo>? _flagMap;
|
||||||
|
|
||||||
|
// pizzaboxer wanted this
|
||||||
|
private void ParseLaunchFlagProps()
|
||||||
|
{
|
||||||
|
_flagMap = new Dictionary<string, PropertyInfo>();
|
||||||
|
|
||||||
|
foreach (var prop in typeof(LaunchSettings).GetProperties())
|
||||||
|
{
|
||||||
|
var attr = prop.GetCustomAttribute<LaunchFlagAttribute>();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
Bloxstrap/Models/Attributes/LaunchFlagAttribute.cs
Normal file
24
Bloxstrap/Models/Attributes/LaunchFlagAttribute.cs
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
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;
|
return defaultResult;
|
||||||
|
|
||||||
switch (App.Settings.Prop.BootstrapperStyle)
|
switch (App.Settings.Prop.BootstrapperStyle)
|
||||||
|
Loading…
Reference in New Issue
Block a user