From bd7f3f603329111996813066ea95c85b2c4ca964 Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 20 Jun 2022 15:50:32 +0200 Subject: [PATCH] feat: continuously check for game window, don't use WaitForInputIdle(), throw exception if timeout --- Dalamud.Injector/EntryPoint.cs | 4 +++ Dalamud.Injector/NativeAclFix.cs | 47 +++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/Dalamud.Injector/EntryPoint.cs b/Dalamud.Injector/EntryPoint.cs index 1539a18e0..48d86d160 100644 --- a/Dalamud.Injector/EntryPoint.cs +++ b/Dalamud.Injector/EntryPoint.cs @@ -604,9 +604,13 @@ namespace Dalamud.Injector Log.Error("[HOOKS] RewriteRemoteEntryPointW failed"); throw new Exception("RewriteRemoteEntryPointW failed"); } + + Log.Verbose("RewriteRemoteEntryPointW called!"); } }); + Log.Verbose("Game process started with PID {0}", process.Id); + if (!withoutDalamud && mode == "inject") { var startInfo = AdjustStartInfo(dalamudStartInfo, gamePath); diff --git a/Dalamud.Injector/NativeAclFix.cs b/Dalamud.Injector/NativeAclFix.cs index 1200bfcf7..5f14bce26 100644 --- a/Dalamud.Injector/NativeAclFix.cs +++ b/Dalamud.Injector/NativeAclFix.cs @@ -24,13 +24,14 @@ namespace Dalamud.Injector /// Arguments to pass to the executable file. /// Don't actually fix the ACL. /// Action to execute before the process is started. + /// Wait for the game window to be ready before proceeding. /// The started process. /// Thrown when a win32 error occurs. - /// Thrown when the process did not start correctly. - public static Process LaunchGame(string workingDir, string exePath, string arguments, bool dontFixAcl, Action beforeResume) + /// Thrown when the process did not start correctly. + public static Process LaunchGame(string workingDir, string exePath, string arguments, bool dontFixAcl, Action beforeResume, bool waitForGameWindow = true) { Process process = null; - + var psecDesc = IntPtr.Zero; if (!dontFixAcl) { @@ -121,19 +122,32 @@ namespace Dalamud.Injector PInvoke.ResumeThread(lpProcessInformation.hThread); // Ensure that the game main window is prepared - try + if (waitForGameWindow) { - do + try { - process.WaitForInputIdle(); + var tries = 0; + const int maxTries = 120; + const int timeout = 50; - Thread.Sleep(100); + do + { + Thread.Sleep(timeout); + + if (process.HasExited) + throw new GameStartException(); + + if (tries > maxTries) + throw new GameStartException($"Couldn't find game window after {maxTries * timeout}ms"); + + tries++; + } + while (TryFindGameWindow(process) == IntPtr.Zero); + } + catch (InvalidOperationException) + { + throw new GameStartException("Could not read process information."); } - while (TryFindGameWindow(process) == IntPtr.Zero); - } - catch (InvalidOperationException) - { - throw new GameExitedException(); } if (!dontFixAcl) @@ -309,13 +323,14 @@ namespace Dalamud.Injector /// /// Exception thrown when the process has exited before a window could be found. /// - public class GameExitedException : Exception + public class GameStartException : Exception { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public GameExitedException() - : base("Game exited prematurely.") + /// The message to pass on. + public GameStartException(string? message = null) + : base(message ?? "Game exited prematurely.") { } }