/// <summary> /// Starts the game execution sequence. Catches all exceptions and shows a message box (which currently doesn't work because run on separate thread). /// </summary> public void Start() { try { // We want to get the game running since we are.. you know.. the game runner. heh. _game = Steam.LaunchGame(_gameId); // Begin game runner execution Execute(); } catch (InvalidSteamUserException ex) { MessageBox.Show("Invalid Steam User"); } catch (GameNotInstalledException ex) { MessageBox.Show("Game is invalid or not installed"); } catch (GameUpdatingException ex) { MessageBox.Show("Game is currently updating and in bad state"); } catch (Exception ex) { Console.WriteLine("ERROR"); Console.WriteLine(ex.Message); Console.WriteLine("END ERROR"); MessageBox.Show(string.Format("Unknown error occurred: {0}", ex.Message)); } // finally close the game finally { try { if (IsRunning && !Steam.CloseGame(_game)) { throw new Exception("Failed to close game, process may still be running."); } Console.WriteLine("Successfully closed game."); } catch (Exception ex) { MessageBox.Show("Failed to close game"); } finally { _game = null; // Any child can override and do specific cleanup OnExiting(); } } }
/// <summary> /// Closes the specified game object by closing its window and returns once the process is dead. /// </summary> /// <param name="game">the steam game object to be killed</param> /// <returns>true if successfully destroyed the process, false otherwise</returns> public static bool CloseGame(SteamGame game) { Console.WriteLine("Attempting to close game."); game.Window?.Close(); while (game.IsRunning) { Thread.Sleep(500); Console.WriteLine("Attempting to close game."); } return(game.Window == null); }
/// <summary> /// Launches a steam game if it is not already in the middle of launching or running. Creates a new SteamGame object which wraps /// the game process and window and returns it when the game is running. Should not be run on main thread. /// </summary> /// <param name="gameId">Steam app ID to launch</param> /// <returns>Game wrapper representing the new running steam game process and window</returns> public static SteamGame LaunchGame(int gameId) { if (!IsLoggedIn) { throw new InvalidSteamUserException("User is not logged in"); } SteamGame game = new SteamGame(gameId); // Throw an exception if the game is not installed if (!game.IsInstalled) { throw new GameNotInstalledException(); } // Throw an exception if the game is updating and not usable if (game.IsUpdating) { throw new GameUpdatingException(); } // Launches the steam launcher process only if the game is not already launching if (!game.IsRunning && !game.IsLaunching) { string steamLauncherProcessUri = string.Format(STEAM_LAUNCH_URI, gameId); using (Process steamLauncherProcess = Process.Start(steamLauncherProcessUri)) { // should almost be instant as the process' job is to // create the actual game launcher process. Process-ception. steamLauncherProcess.WaitForExit(); } } // Wait until the game's process has updated to be running with a valid window handle // before returning the game object to the consumer. // TODO: Probably want to have a max time limit or check counter so this doesn't go on forever. while (!game.IsRunning || game.Window == null) { Thread.Sleep(500); } // Game should now be foregrounded return(game); }
/// <summary> /// Constructs an instruction set /// </summary> /// <param name="game">the Steam game to run the instructions on</param> public InstructionSet(SteamGame game) { this.Game = game; }