diff --git a/DisplayMagician/Properties/AssemblyInfo.cs b/DisplayMagician/Properties/AssemblyInfo.cs index d23ed95..9035efc 100644 --- a/DisplayMagician/Properties/AssemblyInfo.cs +++ b/DisplayMagician/Properties/AssemblyInfo.cs @@ -26,8 +26,8 @@ using System.Resources; [assembly: Guid("e4ceaf5e-ad01-4695-b179-31168eb74c48")] // Version information -[assembly: AssemblyVersion("2.3.0.16")] -[assembly: AssemblyFileVersion("2.3.0.16")] +[assembly: AssemblyVersion("2.3.0.21")] +[assembly: AssemblyFileVersion("2.3.0.21")] [assembly: NeutralResourcesLanguageAttribute( "en" )] [assembly: CLSCompliant(true)] diff --git a/DisplayMagician/ShortcutItem.cs b/DisplayMagician/ShortcutItem.cs index 56e09ce..8854c93 100644 --- a/DisplayMagician/ShortcutItem.cs +++ b/DisplayMagician/ShortcutItem.cs @@ -125,24 +125,24 @@ namespace DisplayMagician private ShortcutCategory _category = ShortcutCategory.Game; private string _differentExecutableToMonitor; private string _executableNameAndPath = ""; - private string _executableArguments; + private string _executableArguments = ""; private bool _executableArgumentsRequired = false; private bool _runExeAsAdministrator = false; private bool _processNameToMonitorUsesExecutable = true; private ProcessPriority _processPriority = ProcessPriority.Normal; - private string _gameAppId; - private string _gameName; + private string _gameAppId = ""; + private string _gameName = ""; private SupportedGameLibraryType _gameLibrary = SupportedGameLibraryType.Unknown; private int _startTimeout = 20; - private string _gameArguments; - private bool _gameArgumentsRequired; - private string _differentGameExeToMonitor; + private string _gameArguments = ""; + private bool _gameArgumentsRequired = false; + private string _differentGameExeToMonitor = ""; private bool _monitorDifferentGameExe = false; - private string _audioDevice; - private bool _changeAudioDevice; + private string _audioDevice = ""; + private bool _changeAudioDevice = false; private bool _setAudioVolume = false; private decimal _audioVolume = -1; - private string _captureDevice; + private string _captureDevice = ""; private bool _changeCaptureDevice; private bool _setCaptureVolume = false; private decimal _captureVolume = -1; diff --git a/DisplayMagician/ShortcutRepository.cs b/DisplayMagician/ShortcutRepository.cs index 8fafda1..9197084 100644 --- a/DisplayMagician/ShortcutRepository.cs +++ b/DisplayMagician/ShortcutRepository.cs @@ -955,7 +955,8 @@ namespace DisplayMagician // If required, check whether a process is started already if (processToStart.DontStartIfAlreadyRunning) { - logger.Info($"ShortcutRepository/RunShortcut: Checking if process {processToStart.Executable} is already running"); + logger.Trace($"ShortcutRepository/RunShortcut: User wants us to only start {processToStart.Executable} if there are no other instances already running"); + logger.Trace($"ShortcutRepository/RunShortcut: Checking if process {processToStart.Executable} is already running"); Process[] alreadyRunningProcesses = System.Diagnostics.Process.GetProcessesByName(Path.GetFileNameWithoutExtension(processToStart.Executable)); if (alreadyRunningProcesses.Length > 0) { @@ -1005,7 +1006,24 @@ namespace DisplayMagician logger.Debug($"ShortcutRepository/RunShortcut: No need to stop {p.StartInfo.FileName} after the main game or executable is closed, so we'll just leave it running"); } } - } + } + else + { + // Find out if there are already other similarly named processes running + Process[] alreadyRunningProcesses = System.Diagnostics.Process.GetProcessesByName(Path.GetFileNameWithoutExtension(processToStart.Executable)); + if (alreadyRunningProcesses.Length == 0) + { + logger.Warn($"ShortcutRepository/RunShortcut: Couldn't start {processToStart.Executable}, and there were no other instances of it previously running either. It is possible that the program requires user interaction, or that there is a problem with it. Please try running '{processToStart.Executable}' yourself to see if it actually works."); + } + else if (alreadyRunningProcesses.Length == 1) + { + logger.Info($"ShortcutRepository/RunShortcut: There is already one other instance of {processToStart.Executable} running, and the additional instance we tried to start didn't start. It is likely that the application we tried to start is a 'single instance' application, meaning that any additional {processToStart.Executable} we try to start will simply pass their command line parameters to the single instance and then will shut themselves down. This is expected behaviour for these types of executables."); + } + else + { + logger.Info($"ShortcutRepository/RunShortcut: There are already {alreadyRunningProcesses.Length} instances of {processToStart.Executable} already running, and the latest instance we tried to start didn't start."); + } + } } catch (Win32Exception ex) { @@ -1924,7 +1942,7 @@ namespace DisplayMagician ProcessUtils.StopProcess(startProgramsToStop); // Refresh the system tray / notification tray area to clean out any applications we stopped - DisplayMagicianShared.Windows.WinLibrary.RefreshTrayArea(); + WinLibrary.RefreshTrayArea(); } diff --git a/DisplayMagician/UIForms/ShortcutForm.cs b/DisplayMagician/UIForms/ShortcutForm.cs index c8a6287..d628188 100644 --- a/DisplayMagician/UIForms/ShortcutForm.cs +++ b/DisplayMagician/UIForms/ShortcutForm.cs @@ -797,13 +797,14 @@ namespace DisplayMagician.UIForms { // Check the name is valid to save if (String.IsNullOrWhiteSpace(txt_shortcut_save_name.Text)) - { + {logger.Error($"ShortcutForm/CanEnableSaveButton: The application doesn't have an executable listed the shortcut"); return false; } // Check the profile is set and that it's still valid if (!(_profileToUse is ProfileItem)) { + logger.Error($"ShortcutForm/CanEnableSaveButton: The shortcut doesn't have a profile assigned to it!"); return false; } @@ -812,22 +813,26 @@ namespace DisplayMagician.UIForms { if (cb_args_executable.Checked && String.IsNullOrWhiteSpace(txt_args_executable.Text)) { + logger.Error($"ShortcutForm/CanEnableSaveButton: The application doesn't have an executable listed"); return false; } if (!File.Exists(txt_executable.Text)) { + logger.Error($"ShortcutForm/CanEnableSaveButton: The application executable {txt_executable.Text} doesn't exist. Please check the file '{txt_executable.Text}' is still there, and that the file has the correct permissions."); return false; } if (rb_wait_alternative_executable.Checked && String.IsNullOrWhiteSpace(txt_alternative_executable.Text)) { + logger.Error($"ShortcutForm/CanEnableSaveButton: The user asked to wait for an alternative application executable, but failed to provide one!"); return false; } if (rb_wait_alternative_executable.Checked && !File.Exists(txt_alternative_executable.Text)) { + logger.Error($"ShortcutForm/CanEnableSaveButton: The alternative application executable the user wants to monitor doesn't exist. Please check the file '{txt_alternative_executable.Text}' is still there, and that the file has the correct permissions."); return false; } @@ -837,11 +842,13 @@ namespace DisplayMagician.UIForms if (cb_args_game.Checked && String.IsNullOrWhiteSpace(txt_args_game.Text)) { + logger.Error($"ShortcutForm/CanEnableSaveButton: The user wanted to pass arguments to the game executable, but failed to provide any!"); return false; } if (_gameId.Equals("0")) { + logger.Error($"ShortcutForm/CanEnableSaveButton: The game ID provided is 0, and this is invalid. We cannot run the game."); return false; } @@ -857,23 +864,39 @@ namespace DisplayMagician.UIForms } if (!gameStillInstalled) { + logger.Error($"ShortcutForm/CanEnableSaveButton: The {_gameLauncher} game with ID {_gameId} isn't installed at present, so can't be used!"); return false; } if (cb_wait_alternative_game.Checked && String.IsNullOrWhiteSpace(txt_alternative_game.Text)) { + logger.Error($"ShortcutForm/CanEnableSaveButton: The user asked to wait for an alternative game executable, but failed to provide one!"); return false; } if (cb_wait_alternative_game.Checked && !File.Exists(txt_alternative_game.Text)) { + logger.Error($"ShortcutForm/CanEnableSaveButton: The alternative game executable the user wants to monitor doesn't exist. Please check the file '{txt_alternative_game.Text}' is still there, and that the file has the correct permissions."); return false; } } + // Look for any start programs without an exe + List startProgramsToStartWithoutExe = _shortcutToEdit.StartPrograms.Where(program => program.Executable == null).ToList(); + if (startProgramsToStartWithoutExe.Count > 0) + { + foreach (StartProgram myStartProgram in startProgramsToStartWithoutExe) + { + logger.Error($"ShortcutForm/CanEnableSaveButton: The start program at position #{myStartProgram.Priority} doesn't have an executable listed"); + } + return false; + } + + // Check the stop program has an exe in there if (cb_run_cmd_afterwards.Checked && String.IsNullOrWhiteSpace(txt_run_cmd_afterwards.Text)) { + logger.Error($"ShortcutForm/CanEnableSaveButton: The run command afterwards command is selected, yet doesn't have an executable listed"); return false; } @@ -1437,7 +1460,7 @@ namespace DisplayMagician.UIForms { logger.Warn($"ShortcutForm/ShortcutForm_Load: Start program #{myStartProgram.Priority} is empty, so skipping."); continue; - } + } StartProgramControl startProgramControl = new StartProgramControl(myStartProgram, spOrder); startProgramControl.Dock = DockStyle.None; @@ -3060,7 +3083,9 @@ namespace DisplayMagician.UIForms { // Create a new startProgram with sensible defaults StartProgram newStartProgram = new StartProgram() { - CloseOnFinish = true + CloseOnFinish = true, + Executable = "", + Arguments = "", }; StartProgramControl newStartProgramControl = new StartProgramControl(newStartProgram, flp_start_programs.Controls.Count); newStartProgramControl.Dock = DockStyle.None; diff --git a/DisplayMagician/UIForms/StartProgramControl.cs b/DisplayMagician/UIForms/StartProgramControl.cs index ccc2aa4..a6a7351 100644 --- a/DisplayMagician/UIForms/StartProgramControl.cs +++ b/DisplayMagician/UIForms/StartProgramControl.cs @@ -32,6 +32,27 @@ namespace DisplayMagician.UIForms public StartProgramControl() { InitializeComponent(); + + // Patch any null start programs (old error that needs repairing) + // This code will save the file as it should be saved! + if (myStartProgram.Arguments == null) + { + myStartProgram.Arguments = ""; + } + + // Prepare the start program process priority combo box + cbx_start_program_priority.DataSource = new ComboItem[] { + new ComboItem{ Value = ProcessPriority.High, Text = "High" }, + new ComboItem{ Value = ProcessPriority.AboveNormal, Text = "Above Normal" }, + new ComboItem{ Value = ProcessPriority.Normal, Text = "Normal" }, + new ComboItem{ Value = ProcessPriority.BelowNormal, Text = "Below Normal" }, + new ComboItem{ Value = ProcessPriority.Idle, Text = "Idle" }, + }; + cbx_start_program_priority.ValueMember = "Value"; + cbx_start_program_priority.DisplayMember = "Text"; + cbx_start_program_priority.SelectedItem = "Normal"; + cbx_start_program_priority.Enabled = true; + } public StartProgramControl(StartProgram startProgram) @@ -40,6 +61,28 @@ namespace DisplayMagician.UIForms // Update the text with the start program info myStartProgram = startProgram; + + // Patch any null start programs (old error that needs repairing) + // This code will save the file as it should be saved! + if (myStartProgram.Arguments == null) + { + myStartProgram.Arguments = ""; + } + + // Prepare the start program process priority combo box + cbx_start_program_priority.DataSource = new ComboItem[] { + new ComboItem{ Value = ProcessPriority.High, Text = "High" }, + new ComboItem{ Value = ProcessPriority.AboveNormal, Text = "Above Normal" }, + new ComboItem{ Value = ProcessPriority.Normal, Text = "Normal" }, + new ComboItem{ Value = ProcessPriority.BelowNormal, Text = "Below Normal" }, + new ComboItem{ Value = ProcessPriority.Idle, Text = "Idle" }, + }; + cbx_start_program_priority.ValueMember = "Value"; + cbx_start_program_priority.DisplayMember = "Text"; + cbx_start_program_priority.SelectedItem = "Normal"; + cbx_start_program_priority.Enabled = true; + + UpdateUI(); } @@ -51,6 +94,13 @@ namespace DisplayMagician.UIForms myStartProgram = startProgram; myStartProgram.Priority = startProgramOrder; + // Patch any null start programs (old error that needs repairing) + // This code will save the file as it should be saved! + if (myStartProgram.Arguments == null) + { + myStartProgram.Arguments = ""; + } + // Prepare the start program process priority combo box cbx_start_program_priority.DataSource = new ComboItem[] { new ComboItem{ Value = ProcessPriority.High, Text = "High" },