diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 0fc6171..1844cf5 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -212,7 +212,9 @@ namespace Bloxstrap await mutex.ReleaseAsync(); if (!App.LaunchSettings.NoLaunchFlag.Active && !_cancelFired) - await StartRoblox(); + StartRoblox(); + + Dialog?.CloseBootstrapper(); } private async Task CheckLatestVersion() @@ -273,7 +275,7 @@ namespace Bloxstrap _versionPackageManifest = await PackageManifest.Get(_latestVersionGuid); } - private async Task StartRoblox() + private void StartRoblox() { const string LOG_IDENT = "Bootstrapper::StartRoblox"; @@ -287,6 +289,12 @@ namespace Bloxstrap _launchCommandLine = _launchCommandLine.Replace("robloxLocale:en_us", $"robloxLocale:{match.Groups[1].Value}", StringComparison.InvariantCultureIgnoreCase); } + // needed for the start event to fire + if (!String.IsNullOrEmpty(_launchCommandLine)) + _launchCommandLine += " "; + + _launchCommandLine += "-isInstallerLaunch"; + var startInfo = new ProcessStartInfo() { FileName = _playerLocation, @@ -297,10 +305,11 @@ namespace Bloxstrap if (_launchMode == LaunchMode.StudioAuth) { Process.Start(startInfo); - Dialog?.CloseBootstrapper(); return; } + using var startEvent = new EventWaitHandle(false, EventResetMode.ManualReset, "www.roblox.com/robloxStartedEvent"); + // v2.2.0 - byfron will trip if we keep a process handle open for over a minute, so we're doing this now int gameClientPid; using (var gameClient = Process.Start(startInfo)!) @@ -308,20 +317,16 @@ namespace Bloxstrap gameClientPid = gameClient.Id; } - App.Logger.WriteLine(LOG_IDENT, $"Started Roblox (PID {gameClientPid})"); + App.Logger.WriteLine(LOG_IDENT, $"Started Roblox (PID {gameClientPid}), waiting for start event"); - using (var startEvent = new SystemEvent(AppData.StartEvent)) + if (!startEvent.WaitOne(TimeSpan.FromSeconds(10))) { - // TODO: get rid of this - bool startEventFired = await startEvent.WaitForEvent(); - - startEvent.Close(); - - // TODO: this cannot silently exit like this - if (!startEventFired) - return; + Frontend.ShowPlayerErrorDialog(); + return; } + App.Logger.WriteLine(LOG_IDENT, "Start event signalled"); + var autoclosePids = new List(); // launch custom integrations now @@ -352,20 +357,17 @@ namespace Bloxstrap autoclosePids.Add(pid); } - using (var proclock = new InterProcessLock("Watcher")) + + string args = gameClientPid.ToString(); + + if (autoclosePids.Any()) + args += $";{String.Join(',', autoclosePids)}"; + + using (var ipl = new InterProcessLock("Watcher")) { - string args = gameClientPid.ToString(); - - if (autoclosePids.Any()) - args += $";{String.Join(',', autoclosePids)}"; - - if (proclock.IsAcquired) + if (ipl.IsAcquired) Process.Start(Paths.Process, $"-watcher \"{args}\""); } - - // event fired, wait for 3 seconds then close - await Task.Delay(3000); - Dialog?.CloseBootstrapper(); } public void CancelInstall() diff --git a/Bloxstrap/Resources/Strings.Designer.cs b/Bloxstrap/Resources/Strings.Designer.cs index 1ce1035..b70ee99 100644 --- a/Bloxstrap/Resources/Strings.Designer.cs +++ b/Bloxstrap/Resources/Strings.Designer.cs @@ -886,6 +886,33 @@ namespace Bloxstrap.Resources { } } + /// + /// Looks up a localized string similar to Roblox has crashed.. + /// + public static string Dialog_PlayerError_Crash { + get { + return ResourceManager.GetString("Dialog.PlayerError.Crash", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Roblox failed to launch.. + /// + public static string Dialog_PlayerError_FailedLaunch { + get { + return ResourceManager.GetString("Dialog.PlayerError.FailedLaunch", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please read the following help information, which will open in your web browser when you close this dialog.. + /// + public static string Dialog_PlayerError_HelpInformation { + get { + return ResourceManager.GetString("Dialog.PlayerError.HelpInformation", resourceCulture); + } + } + /// /// Looks up a localized string similar to Early 2015. /// diff --git a/Bloxstrap/Resources/Strings.resx b/Bloxstrap/Resources/Strings.resx index 52c7f52..301c5c9 100644 --- a/Bloxstrap/Resources/Strings.resx +++ b/Bloxstrap/Resources/Strings.resx @@ -1144,4 +1144,13 @@ If not, then please report this exception to the maintainers of this fork. Do NO Issues may occur and your settings may be altered. A reinstall is recommended. Are you sure you want to continue? + + Roblox failed to launch. + + + Roblox has crashed. + + + Please read the following help information, which will open in your web browser when you close this dialog. + \ No newline at end of file diff --git a/Bloxstrap/UI/Frontend.cs b/Bloxstrap/UI/Frontend.cs index af21245..1699b6b 100644 --- a/Bloxstrap/UI/Frontend.cs +++ b/Bloxstrap/UI/Frontend.cs @@ -33,6 +33,20 @@ namespace Bloxstrap.UI } } + public static void ShowPlayerErrorDialog(bool crash = false) + { + if (App.LaunchSettings.QuietFlag.Active) + return; + + string topLine = Strings.Dialog_PlayerError_FailedLaunch; + + if (crash) + topLine = Strings.Dialog_PlayerError_Crash; + + ShowMessageBox($"{topLine}\n\n{Strings.Dialog_PlayerError_HelpInformation}", MessageBoxImage.Error); + Utilities.ShellExecute($"https://github.com/{App.ProjectRepository}/wiki/Roblox-crashes-or-does-not-launch"); + } + public static void ShowExceptionDialog(Exception exception) { Application.Current.Dispatcher.Invoke(() => diff --git a/Bloxstrap/Utility/SystemEvent.cs b/Bloxstrap/Utility/SystemEvent.cs deleted file mode 100644 index f4b4746..0000000 --- a/Bloxstrap/Utility/SystemEvent.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Roblox Studio Mod Manager (ProjectSrc/Utility/SystemEvent.cs) - * MIT License - * Copyright (c) 2015-present MaximumADHD -*/ - -namespace Bloxstrap.Utility -{ - public class SystemEvent : EventWaitHandle - { - public string Name { get; private set; } - - public SystemEvent(string name, bool init = false, EventResetMode mode = EventResetMode.AutoReset) : base(init, mode, name) - { - if (init) - Reset(); - else - Set(); - - Name = name; - } - - public override string ToString() - { - return Name; - } - - public Task WaitForEvent() - { - return Task.Run(WaitOne); - } - - public Task WaitForEvent(TimeSpan timeout, bool exitContext = false) - { - return Task.Run(() => WaitOne(timeout, exitContext)); - } - - public Task WaitForEvent(int millisecondsTimeout, bool exitContext = false) - { - return Task.Run(() => WaitOne(millisecondsTimeout, exitContext)); - } - } -}