public async Task KillLauncherAsync() { IUserMessage response; EmbedBuilder initialBuilder; initialBuilder = EmbedHelper.GetDefaultEmbed(Context); initialBuilder.AddField(":gun: Killing GTA Launcher", "Please wait..."); response = await ReplyAsync("", embed : initialBuilder.Build()); try { Process launcherProcess; ProcessProvider provider; EmbedBuilder embed; embed = EmbedHelper.GetDefaultEmbed(Context); provider = new ProcessProvider(); launcherProcess = provider.GetGrandTheftAutoLauncherProcess(); if (launcherProcess != null) { launcherProcess.Kill(); } else { EventLogLogger.LogWarning("Attempted to kill the GTA Launcher process but the process could not be found."); } embed.AddField(":white_check_mark: Success", "The launcher process has been killed."); await response.ModifyAsync(msg => { msg.Embed = embed.Build(); msg.Content = ""; }); } catch (Exception e) { await response.ModifyAsync(msg => msg = ErrorHandler.GetDefaultErrorMessageEmbed(e, msg, Context.Message)); } }
/// <summary> /// Forcibly kills the GTA process and the associated launcher process. /// Throws argument exceptions if the process are unable to be found, /// or if they are still alive after being killed. /// </summary> private void KillGTAProcess() { Process process; Process launcherProcess; ProcessProvider provider; int timeout; provider = new ProcessProvider(); process = provider.GetGrandTheftAutoProcess(); timeout = 0; if (process != null) { process.Kill(); } else { throw new ApplicationException("Unable to locate GTA V process."); } do { // While the process has not exited, wait for a bit and then check again. // If we wait for a period of 30 seconds then exit out of the loop and // throw an exception because we do not want to end up in an infinite loop. Thread.Sleep(1000); timeout++; } while (!process.HasExited && (timeout < 30)); if (timeout >= 30) { // If we hit the timeout, throw an exception and log the error. throw new ApplicationException("Timed out trying to exit the GTA V process"); } // TODO: This is nasty, really nasty, but Rockstar can't program // a game properly so I guess this is what we're left with. The launcher process // acts as a giant try-catch statement around the entire of GTA, so if GTA crashes // or is killed by force, the launcher process will pop up with the usual 'safe mode' // message. // // The problem with this is that the launcher needs time to start up, as it seems as if // it sets a flag of some kind to tell itself that it has already prompted the user with // the 'safe mode' warning message. If the launcher process never has time to initialize when // the game is killed, then it never gets to set the flag to say it warned the user. // As a result of this, the next time the game is started, because it relies on the launcher // process to instance the game, it will show up the 'safe mode' dialog and stop us from // launching the game until the dialog is dealt with. Thread.Sleep(5000); // Get the launcher process, this is needed because GTA is special and will try to // catch all exceptions that occur, and pop up an annoying 'Safe Mode' dialog. This is // annoying and useless, we have no other way to stop GTA quickly other than a force // quit so this dialog is expected. If we find it, kill it. It serves no purpose for us. launcherProcess = provider.GetGrandTheftAutoLauncherProcess(); if (launcherProcess != null) { launcherProcess.Kill(); } }