From 41f336f3e7943a8b77f6a64c398894ec8ad48600 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 29 Jun 2024 21:05:03 -0600 Subject: [PATCH] don't wait for ed to exit before exiting when autoquit closes #131 --- CHANGELOG.md | 6 ++++- src/MinEdLauncher/App.fs | 51 +++++++++++++++++++++++------------- src/MinEdLauncher/Product.fs | 10 +++++++ 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 243335f..c874f59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,11 @@ or [Heroic]. Once you've logged in with either, you can go back to using the normal Epic launcher if you wish. It will require re-logging in every few days though, so it may be preferable to just stick with the alternate launchers. - Added an [icon](resources/min-ed-launcher.svg) for the app. Linux users can check the [readme](README.md#icon-on-linux) - for setup instructions. + for setup instructions. +- The launcher will now exit instead of waiting for Elite to exit if the following conditions are met: + 1. `/autoquit` is specified + 2. `/restart` is not specified + 3. No external apps specified in `settings.json` (`processes`, `shutdownProcesses`) ## [0.10.1] - 2024-05-03 diff --git a/src/MinEdLauncher/App.fs b/src/MinEdLauncher/App.fs index ac634a7..af95ca1 100644 --- a/src/MinEdLauncher/App.fs +++ b/src/MinEdLauncher/App.fs @@ -98,18 +98,19 @@ let private checkForLauncherUpdates httpClient cancellationToken currentVersion ) } -let launchProduct dryRun proton processArgs productName product = +let launchProduct dryRun proton processArgs productName waitForExit product = let args = processArgs() Log.info $"Launching %s{productName}" match Product.run dryRun proton args product with | Product.RunResult.Ok p -> - use p = p p.BeginErrorReadLine() p.BeginOutputReadLine() - p.WaitForExit() - p.Close() - Log.info $"Shutdown %s{productName}" + if waitForExit then + use p = p + p.WaitForExit() + p.Close() + Log.info $"Shutdown %s{productName}" | Product.DryRun p -> Console.WriteLine("\tDry run") Console.WriteLine($"\t{p.FileName} {p.Arguments}") @@ -337,22 +338,36 @@ let rec private launchLoop initialLaunch settings playableProducts (session: EdS Log.info $"Delaying game launch for %.2f{settings.GameStartDelay.TotalSeconds} seconds" do! Task.Delay settings.GameStartDelay - launchProduct settings.DryRun settings.CompatTool pArgs selectedProduct.Name p + let waitForEdExit = not settings.AutoQuit || settings.Restart.IsSome || not settings.Processes.IsEmpty || not settings.ShutdownProcesses.IsEmpty - let timeout = settings.Restart |> Option.defaultValue 3000L - while settings.Restart.IsSome && not (Console.cancelRestart timeout) do - Process.stopProcesses settings.ShutdownTimeout relaunchProcesses - logStart relaunchStartInfos - relaunchProcesses <- Process.launchProcesses relaunchStartInfos - - do! renewEpicTokenIfNeeded settings.Platform session.PlatformToken - - launchProduct settings.DryRun settings.CompatTool pArgs selectedProduct.Name p + launchProduct settings.DryRun settings.CompatTool pArgs selectedProduct.Name waitForEdExit p - if not settings.AutoQuit then - return! launchLoop false settings playableProducts session (Some persistentProcesses) (Some relaunchProcesses) cancellationToken processArgs + if not waitForEdExit then + // Wait for ED Process to start before exiting + let maxTries = 30 + let mutable tries = 0 + while tries < maxTries do + if not (Product.isRunning p) then + do! Task.Delay(TimeSpan.FromSeconds(1)) + tries <- tries + 1 + else + tries <- maxTries + return [], didLoop else - return persistentProcesses @ relaunchProcesses, didLoop + let timeout = settings.Restart |> Option.defaultValue 3000L + while settings.Restart.IsSome && not (Console.cancelRestart timeout) do + Process.stopProcesses settings.ShutdownTimeout relaunchProcesses + logStart relaunchStartInfos + relaunchProcesses <- Process.launchProcesses relaunchStartInfos + + do! renewEpicTokenIfNeeded settings.Platform session.PlatformToken + + launchProduct settings.DryRun settings.CompatTool pArgs selectedProduct.Name true p + + if not settings.AutoQuit then + return! launchLoop false settings playableProducts session (Some persistentProcesses) (Some relaunchProcesses) cancellationToken processArgs + else + return persistentProcesses @ relaunchProcesses, didLoop } let run settings launcherVersion cancellationToken = taskResult { diff --git a/src/MinEdLauncher/Product.fs b/src/MinEdLauncher/Product.fs index 2592cf0..9bb8dab 100644 --- a/src/MinEdLauncher/Product.fs +++ b/src/MinEdLauncher/Product.fs @@ -247,6 +247,16 @@ let validateForRun launcherDir watchForCrashes (product: ProductDetails) = Mode = product.VInfo.Mode ServerArgs = product.ServerArgs } +let isRunning (product:RunnableProduct) = + let exeName = Path.GetFileNameWithoutExtension(product.Executable.Name) + + if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then + Process.GetProcessesByName(exeName).Length > 0 + else + // Process.ProcessName seems to be truncated on linux. Not sure if it's always the case or only sometimes + // so check both truncated name and full name + Process.GetProcessesByName(exeName[..14]).Length > 0 || Process.GetProcessesByName(exeName).Length > 0 + let createProcessInfo proton args product = let fileName, arguments = match proton with