feat: continuously check for game window, don't use WaitForInputIdle(), throw exception if timeout

This commit is contained in:
goaaats 2022-06-20 15:50:32 +02:00
parent c3e16ad92c
commit bd7f3f6033
No known key found for this signature in database
GPG key ID: 49E2AA8C6A76498B
2 changed files with 35 additions and 16 deletions

View file

@ -604,9 +604,13 @@ namespace Dalamud.Injector
Log.Error("[HOOKS] RewriteRemoteEntryPointW failed"); Log.Error("[HOOKS] RewriteRemoteEntryPointW failed");
throw new Exception("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") if (!withoutDalamud && mode == "inject")
{ {
var startInfo = AdjustStartInfo(dalamudStartInfo, gamePath); var startInfo = AdjustStartInfo(dalamudStartInfo, gamePath);

View file

@ -24,13 +24,14 @@ namespace Dalamud.Injector
/// <param name="arguments">Arguments to pass to the executable file.</param> /// <param name="arguments">Arguments to pass to the executable file.</param>
/// <param name="dontFixAcl">Don't actually fix the ACL.</param> /// <param name="dontFixAcl">Don't actually fix the ACL.</param>
/// <param name="beforeResume">Action to execute before the process is started.</param> /// <param name="beforeResume">Action to execute before the process is started.</param>
/// <param name="waitForGameWindow">Wait for the game window to be ready before proceeding.</param>
/// <returns>The started process.</returns> /// <returns>The started process.</returns>
/// <exception cref="Win32Exception">Thrown when a win32 error occurs.</exception> /// <exception cref="Win32Exception">Thrown when a win32 error occurs.</exception>
/// <exception cref="GameExitedException">Thrown when the process did not start correctly.</exception> /// <exception cref="GameStartException">Thrown when the process did not start correctly.</exception>
public static Process LaunchGame(string workingDir, string exePath, string arguments, bool dontFixAcl, Action<Process> beforeResume) public static Process LaunchGame(string workingDir, string exePath, string arguments, bool dontFixAcl, Action<Process> beforeResume, bool waitForGameWindow = true)
{ {
Process process = null; Process process = null;
var psecDesc = IntPtr.Zero; var psecDesc = IntPtr.Zero;
if (!dontFixAcl) if (!dontFixAcl)
{ {
@ -121,19 +122,32 @@ namespace Dalamud.Injector
PInvoke.ResumeThread(lpProcessInformation.hThread); PInvoke.ResumeThread(lpProcessInformation.hThread);
// Ensure that the game main window is prepared // 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) if (!dontFixAcl)
@ -309,13 +323,14 @@ namespace Dalamud.Injector
/// <summary> /// <summary>
/// Exception thrown when the process has exited before a window could be found. /// Exception thrown when the process has exited before a window could be found.
/// </summary> /// </summary>
public class GameExitedException : Exception public class GameStartException : Exception
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="GameExitedException"/> class. /// Initializes a new instance of the <see cref="GameStartException"/> class.
/// </summary> /// </summary>
public GameExitedException() /// <param name="message">The message to pass on.</param>
: base("Game exited prematurely.") public GameStartException(string? message = null)
: base(message ?? "Game exited prematurely.")
{ {
} }
} }