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

@ -24,13 +24,14 @@ namespace Dalamud.Injector
/// <param name="arguments">Arguments to pass to the executable file.</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="waitForGameWindow">Wait for the game window to be ready before proceeding.</param>
/// <returns>The started process.</returns>
/// <exception cref="Win32Exception">Thrown when a win32 error occurs.</exception>
/// <exception cref="GameExitedException">Thrown when the process did not start correctly.</exception>
public static Process LaunchGame(string workingDir, string exePath, string arguments, bool dontFixAcl, Action<Process> beforeResume)
/// <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, 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
/// <summary>
/// Exception thrown when the process has exited before a window could be found.
/// </summary>
public class GameExitedException : Exception
public class GameStartException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="GameExitedException"/> class.
/// Initializes a new instance of the <see cref="GameStartException"/> class.
/// </summary>
public GameExitedException()
: base("Game exited prematurely.")
/// <param name="message">The message to pass on.</param>
public GameStartException(string? message = null)
: base(message ?? "Game exited prematurely.")
{
}
}