From df2d89bb6926d74a76dc62f199d55b1f73df8600 Mon Sep 17 00:00:00 2001 From: Terry MacDonald Date: Sun, 25 Jul 2021 21:28:09 +1200 Subject: [PATCH] Working Process Priority Have managed to get process priority working, but need to do more testing before I'm sure it works in all scenarios. I don't have enough different game types to test the various different code paths, so thats going to be something that my users will unfortunately need to bug test. Adds feature #29. --- DisplayMagician/GameLibraries/EpicGame.cs | 11 ++- DisplayMagician/GameLibraries/GOGGame.cs | 11 ++- DisplayMagician/GameLibraries/Game.cs | 4 + DisplayMagician/GameLibraries/OriginGame.cs | 11 ++- DisplayMagician/GameLibraries/SteamGame.cs | 11 ++- DisplayMagician/GameLibraries/UplayGame.cs | 11 ++- DisplayMagician/ShortcutRepository.cs | 99 ++++++++++++++++----- DisplayMagician/UIForms/ShortcutForm.cs | 5 +- 8 files changed, 127 insertions(+), 36 deletions(-) diff --git a/DisplayMagician/GameLibraries/EpicGame.cs b/DisplayMagician/GameLibraries/EpicGame.cs index 8141c12..ca43e88 100644 --- a/DisplayMagician/GameLibraries/EpicGame.cs +++ b/DisplayMagician/GameLibraries/EpicGame.cs @@ -16,6 +16,7 @@ namespace DisplayMagician.GameLibraries private string _epicGameDir; private string _epicGameExe; private string _epicGameProcessName; + private List _epicGameProcesses = new List(); private string _epicGameIconPath; //private string _epicURI; private static readonly EpicLibrary _epicGameLibrary = EpicLibrary.GetLibrary(); @@ -90,13 +91,19 @@ namespace DisplayMagician.GameLibraries set => _epicGameProcessName = value; } + public override List Processes + { + get => _epicGameProcesses; + set => _epicGameProcesses = value; + } + public override bool IsRunning { get { int numGameProcesses = 0; - List gameProcesses = Process.GetProcessesByName(_epicGameProcessName).ToList(); - foreach (Process gameProcess in gameProcesses) + _epicGameProcesses = Process.GetProcessesByName(_epicGameProcessName).ToList(); + foreach (Process gameProcess in _epicGameProcesses) { try { diff --git a/DisplayMagician/GameLibraries/GOGGame.cs b/DisplayMagician/GameLibraries/GOGGame.cs index 39990dd..3bc6d83 100644 --- a/DisplayMagician/GameLibraries/GOGGame.cs +++ b/DisplayMagician/GameLibraries/GOGGame.cs @@ -16,6 +16,7 @@ namespace DisplayMagician.GameLibraries private string _gogGameDir; private string _gogGameExe; private string _gogGameProcessName; + private List _gogGameProcesses = new List(); private string _gogGameIconPath; //private string _gogURI; private static readonly GogLibrary _gogGameLibrary = GogLibrary.GetLibrary(); @@ -90,13 +91,19 @@ namespace DisplayMagician.GameLibraries set => _gogGameProcessName = value; } + public override List Processes + { + get => _gogGameProcesses; + set => _gogGameProcesses = value; + } + public override bool IsRunning { get { int numGameProcesses = 0; - List gameProcesses = Process.GetProcessesByName(_gogGameProcessName).ToList(); - foreach (Process gameProcess in gameProcesses) + _gogGameProcesses = Process.GetProcessesByName(_gogGameProcessName).ToList(); + foreach (Process gameProcess in _gogGameProcesses) { try { diff --git a/DisplayMagician/GameLibraries/Game.cs b/DisplayMagician/GameLibraries/Game.cs index fc033dc..78e7c4a 100644 --- a/DisplayMagician/GameLibraries/Game.cs +++ b/DisplayMagician/GameLibraries/Game.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; namespace DisplayMagician.GameLibraries @@ -29,6 +31,8 @@ namespace DisplayMagician.GameLibraries public virtual string ProcessName { get; set; } + public virtual List Processes { get; set; } + public Bitmap GameBitmap { get; set; } #endregion diff --git a/DisplayMagician/GameLibraries/OriginGame.cs b/DisplayMagician/GameLibraries/OriginGame.cs index 037e902..e6aee80 100644 --- a/DisplayMagician/GameLibraries/OriginGame.cs +++ b/DisplayMagician/GameLibraries/OriginGame.cs @@ -16,6 +16,7 @@ namespace DisplayMagician.GameLibraries private string _originGameDir; private string _originGameExe; private string _originGameProcessName; + private List _originGameProcesses = new List(); private string _originGameIconPath; //private string _originURI; private static readonly OriginLibrary _originGameLibrary = OriginLibrary.GetLibrary(); @@ -89,13 +90,19 @@ namespace DisplayMagician.GameLibraries set => _originGameProcessName = value; } + public override List Processes + { + get => _originGameProcesses; + set => _originGameProcesses = value; + } + public override bool IsRunning { get { int numGameProcesses = 0; - List gameProcesses = Process.GetProcessesByName(_originGameProcessName).ToList(); - foreach (Process gameProcess in gameProcesses) + _originGameProcesses = Process.GetProcessesByName(_originGameProcessName).ToList(); + foreach (Process gameProcess in _originGameProcesses) { try { diff --git a/DisplayMagician/GameLibraries/SteamGame.cs b/DisplayMagician/GameLibraries/SteamGame.cs index 0602e57..165dd32 100644 --- a/DisplayMagician/GameLibraries/SteamGame.cs +++ b/DisplayMagician/GameLibraries/SteamGame.cs @@ -19,6 +19,7 @@ namespace DisplayMagician.GameLibraries private string _steamGameDir; private string _steamGameExe; private string _steamGameProcessName; + private List _steamGameProcesses = new List(); private string _steamGameIconPath; private static readonly SteamLibrary _steamGameLibrary = SteamLibrary.GetLibrary(); private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); @@ -88,13 +89,19 @@ namespace DisplayMagician.GameLibraries set => _steamGameProcessName = value; } + public override List Processes + { + get => _steamGameProcesses; + set => _steamGameProcesses = value; + } + public override bool IsRunning { get { int numGameProcesses = 0; - List gameProcesses = Process.GetProcessesByName(_steamGameProcessName).ToList(); - foreach (Process gameProcess in gameProcesses) + _steamGameProcesses = Process.GetProcessesByName(_steamGameProcessName).ToList(); + foreach (Process gameProcess in _steamGameProcesses) { try { diff --git a/DisplayMagician/GameLibraries/UplayGame.cs b/DisplayMagician/GameLibraries/UplayGame.cs index 60daea9..c089189 100644 --- a/DisplayMagician/GameLibraries/UplayGame.cs +++ b/DisplayMagician/GameLibraries/UplayGame.cs @@ -17,6 +17,7 @@ namespace DisplayMagician.GameLibraries private string _uplayGameDir; private string _uplayGameExe; private string _uplayGameProcessName; + private List _uplayGameProcesses = new List(); private string _uplayGameIconPath; private static readonly UplayLibrary _uplayGameLibrary = UplayLibrary.GetLibrary(); private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); @@ -88,13 +89,19 @@ namespace DisplayMagician.GameLibraries set => _uplayGameProcessName = value; } + public override List Processes + { + get => _uplayGameProcesses; + set => _uplayGameProcesses = value; + } + public override bool IsRunning { get { int numGameProcesses = 0; - List gameProcesses = Process.GetProcessesByName(_uplayGameProcessName).ToList(); - foreach (Process gameProcess in gameProcesses) + _uplayGameProcesses = Process.GetProcessesByName(_uplayGameProcessName).ToList(); + foreach (Process gameProcess in _uplayGameProcesses) { try { diff --git a/DisplayMagician/ShortcutRepository.cs b/DisplayMagician/ShortcutRepository.cs index b7d6857..65dcc3c 100644 --- a/DisplayMagician/ShortcutRepository.cs +++ b/DisplayMagician/ShortcutRepository.cs @@ -816,11 +816,19 @@ namespace DisplayMagician { logger.Info($"ShortcutRepository/RunShortcut: Process {processToStart.Executable} is already running, so we won't start a new one, and we won't stop it later"); - foreach (Process runningProcess in alreadyRunningProcesses) + try { - logger.Trace($"ShortcutRepository/RunShortcut: Setting priority of already running process {processToStart.Executable} to {processToStart.ProcessPriority.ToString("G")}"); - runningProcess.PriorityClass = TranslatePriorityClass(processToStart.ProcessPriority); - } + foreach (Process runningProcess in alreadyRunningProcesses) + { + logger.Trace($"ShortcutRepository/RunShortcut: Setting priority of already running process {processToStart.Executable} to {processToStart.ProcessPriority.ToString("G")}"); + runningProcess.PriorityClass = TranslatePriorityClass(processToStart.ProcessPriority); + } + } + catch (Exception ex) + { + logger.Warn(ex, $"ShortcutRepository/RunShortcut: Exception setting priority of already running process {processToStart.Executable} to {processToStart.ProcessPriority.ToString("G")}"); + } + continue; } @@ -840,9 +848,17 @@ namespace DisplayMagician process = System.Diagnostics.Process.Start(processToStart.Executable); } - // Set the process priority to whatever the user wanted - logger.Trace($"ShortcutRepository/RunShortcut: Setting the start program process priority of start program we started to {shortcutToUse.ProcessPriority.ToString("G")}"); - process.PriorityClass = TranslatePriorityClass(processToStart.ProcessPriority); + try + { + // Attempt to set the process priority to whatever the user wanted + logger.Trace($"ShortcutRepository/RunShortcut: Setting the start program process priority of start program we started to {shortcutToUse.ProcessPriority.ToString("G")}"); + process.PriorityClass = TranslatePriorityClass(processToStart.ProcessPriority); + } + catch (Exception ex) + { + logger.Warn(ex, $"ShortcutRepository/RunShortcut: Exception setting the start program process priority of start program we started to {shortcutToUse.ProcessPriority.ToString("G")}"); + } + // Record the program we started so we can close it later if (processToStart.CloseOnFinish) @@ -1002,11 +1018,17 @@ namespace DisplayMagician { logger.Debug($"ShortcutRepository/RunShortcut: Found {processesToMonitor.Count} '{processNameToLookFor}' processes to monitor"); - - foreach (Process monitoredProcess in processesToMonitor) + try { - logger.Trace($"ShortcutRepository/RunShortcut: Setting priority of monitored executable process {processNameToLookFor} to {shortcutToUse.ProcessPriority.ToString("G")}"); - monitoredProcess.PriorityClass = TranslatePriorityClass(shortcutToUse.ProcessPriority); + foreach (Process monitoredProcess in processesToMonitor) + { + logger.Trace($"ShortcutRepository/RunShortcut: Setting priority of monitored executable process {processNameToLookFor} to {shortcutToUse.ProcessPriority.ToString("G")}"); + monitoredProcess.PriorityClass = TranslatePriorityClass(shortcutToUse.ProcessPriority); + } + } + catch(Exception ex) + { + logger.Warn(ex, $"ShortcutRepository/RunShortcut: Exception Setting priority of monitored executable process {processNameToLookFor} to {shortcutToUse.ProcessPriority.ToString("G")}"); } break; @@ -1106,6 +1128,8 @@ namespace DisplayMagician } else if (shortcutToUse.Category.Equals(ShortcutCategory.Game)) { + logger.Info($"ShortcutRepository/RunShortcut: Starting the game that we wanted to run, and that we're going to monitor and watch"); + Game gameToRun = null; GameLibrary gameLibraryToUse = null; @@ -1309,10 +1333,17 @@ namespace DisplayMagician { logger.Debug($"ShortcutRepository/RunShortcut: Found {processesToMonitor.Count} '{altGameProcessToMonitor}' processes to monitor"); - foreach (Process monitoredProcess in processesToMonitor) + try { - logger.Trace($"ShortcutRepository/RunShortcut: Setting priority of alternative game monitored process {altGameProcessToMonitor} to {shortcutToUse.ProcessPriority.ToString("G")}"); - monitoredProcess.PriorityClass = TranslatePriorityClass(shortcutToUse.ProcessPriority); + foreach (Process monitoredProcess in processesToMonitor) + { + logger.Trace($"ShortcutRepository/RunShortcut: Setting priority of alternative game monitored process {altGameProcessToMonitor} to {shortcutToUse.ProcessPriority.ToString("G")}"); + monitoredProcess.PriorityClass = TranslatePriorityClass(shortcutToUse.ProcessPriority); + } + } + catch (Exception ex) + { + logger.Warn(ex, $"ShortcutRepository/RunShortcut: Setting priority of alternative game monitored process {altGameProcessToMonitor} to {shortcutToUse.ProcessPriority.ToString("G")}"); } break; @@ -1322,17 +1353,13 @@ namespace DisplayMagician // any processes yet Thread.Sleep(500); } - // make sure we have an alternative game executable to monitor + // if none of the different game exe files are running, then we need a fallback if (processesToMonitor.Count == 0) { // if we didn't find an alternative game exectuable to monitor, then we need to go for the game executable itself as a fall back logger.Error($"ShortcutRepository/RunShortcut: No Alternative Game Executable '{altGameProcessToMonitor}' processes found before waiting timeout. DisplayMagician was unable to find any alternative processes before the {shortcutToUse.StartTimeout} second timeout"); logger.Info($"ShortcutRepository/RunShortcut: Ignoring monitoring Alternative Game Executable '{altGameProcessToMonitor}' processes. Reverting back to monitoring Game executables '{gameToRun.ProcessName}' instead."); - // First up we want to set the game process priority - logger.Trace($"ShortcutRepository/RunShortcut: Setting priority of standard game monitored process {gameToRun.ExePath} to {shortcutToUse.ProcessPriority.ToString("G")}"); - gameProcess.PriorityClass = TranslatePriorityClass(shortcutToUse.ProcessPriority); - // we wait until the game has started running (*allows for updates to occur) for (int secs = 0; secs <= (shortcutToUse.StartTimeout * 1000); secs += 500) { @@ -1341,6 +1368,20 @@ namespace DisplayMagician { // The game is running! So now we continue processing logger.Debug($"ShortcutRepository/RunShortcut: Found the '{gameToRun.Name}' process has started"); + + try + { + foreach (Process monitoredProcess in gameToRun.Processes) + { + logger.Trace($"ShortcutRepository/RunShortcut: Setting priority of fallback game monitored process {gameToRun.ProcessName} to {shortcutToUse.ProcessPriority.ToString("G")}"); + monitoredProcess.PriorityClass = TranslatePriorityClass(shortcutToUse.ProcessPriority); + } + } + catch (Exception ex) + { + logger.Warn(ex, $"ShortcutRepository/RunShortcut: Exception setting priority of fallback game monitored process {gameToRun.ProcessName} to {shortcutToUse.ProcessPriority.ToString("G")}"); + } + break; } @@ -1436,7 +1477,7 @@ namespace DisplayMagician } else { - // we found alternative game executable processes, so we'll just monitor them + // Otherwise we did find the alternative game executables supplied by the user, so we should monitor them logger.Debug($"ShortcutRepository/RunShortcut: Waiting for alternative game proocess {altGameProcessToMonitor} to exit."); logger.Debug($"ShortcutRepository/RunShortcut: {processesToMonitor.Count} Alternative Game Executable '{altGameProcessToMonitor}' processes are still running"); @@ -1498,9 +1539,7 @@ namespace DisplayMagician else { // we are monitoring the game thats actually running (the most common scenario) - logger.Trace($"ShortcutRepository/RunShortcut: Setting priority of standard game monitored process {gameToRun.Executable} to {shortcutToUse.ProcessPriority.ToString("G")}"); - gameProcess.PriorityClass = TranslatePriorityClass(shortcutToUse.ProcessPriority); - + // Add a status notification icon in the status area if (gameToRun.Name.Length <= 41) notifyIcon.Text = $"DisplayMagician: Running {gameToRun.Name}..."; @@ -1537,6 +1576,20 @@ namespace DisplayMagician { // The game is running! So now we continue processing logger.Debug($"ShortcutRepository/RunShortcut: Found the '{gameToRun.Name}' process has started"); + + try + { + foreach (Process monitoredProcess in gameToRun.Processes) + { + logger.Trace($"ShortcutRepository/RunShortcut: Setting priority of fallback game monitored process {gameToRun.ProcessName} to {shortcutToUse.ProcessPriority.ToString("G")}"); + monitoredProcess.PriorityClass = TranslatePriorityClass(shortcutToUse.ProcessPriority); + } + } + catch(Exception ex) + { + logger.Warn(ex, $"ShortcutRepository/RunShortcut: Exception setting priority of fallback game monitored process {gameToRun.ProcessName} to {shortcutToUse.ProcessPriority.ToString("G")}"); + } + break; } diff --git a/DisplayMagician/UIForms/ShortcutForm.cs b/DisplayMagician/UIForms/ShortcutForm.cs index 9a33dc6..9be77af 100644 --- a/DisplayMagician/UIForms/ShortcutForm.cs +++ b/DisplayMagician/UIForms/ShortcutForm.cs @@ -1201,7 +1201,7 @@ namespace DisplayMagician.UIForms _gameId = _shortcutToEdit.GameAppId; nud_timeout_game.Value = _shortcutToEdit.StartTimeout; txt_args_game.Text = _shortcutToEdit.GameArguments; - cbx_game_priority.SelectedItem = _shortcutToEdit.ProcessPriority; + cbx_game_priority.SelectedValue = _shortcutToEdit.ProcessPriority; if (_shortcutToEdit.GameArgumentsRequired) { cb_args_game.Checked = true; @@ -1214,7 +1214,7 @@ namespace DisplayMagician.UIForms txt_executable.Text = _shortcutToEdit.ExecutableNameAndPath; nud_timeout_executable.Value = _shortcutToEdit.StartTimeout; txt_args_executable.Text = _shortcutToEdit.ExecutableArguments; - cbx_exe_priority.SelectedItem = _shortcutToEdit.ProcessPriority; + cbx_exe_priority.SelectedValue = _shortcutToEdit.ProcessPriority; if (_shortcutToEdit.ExecutableArgumentsRequired) { cb_args_executable.Checked = true; @@ -1239,7 +1239,6 @@ namespace DisplayMagician.UIForms txt_shortcut_save_name.Text = _shortcutToEdit.Name; // Set up the start programs - if (_shortcutToEdit.StartPrograms is List && _shortcutToEdit.StartPrograms.Count > 0) { flp_start_programs.Controls.Clear();