diff --git a/DisplayMagician/GameLibraries/SteamGame.cs b/DisplayMagician/GameLibraries/SteamGame.cs index d9c278d..b0464b6 100644 --- a/DisplayMagician/GameLibraries/SteamGame.cs +++ b/DisplayMagician/GameLibraries/SteamGame.cs @@ -3,39 +3,15 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; -using System.Reflection; using System.Security; -using System.Drawing; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; using DisplayMagician.Resources; -using DisplayMagician.Shared; -//using HtmlAgilityPack; using Microsoft.Win32; -using Newtonsoft.Json; -//using VdfParser; -//using Gameloop.Vdf; -using System.Collections.ObjectModel; -using ValveKeyValue; -using System.Security.Cryptography; -using System.ServiceModel.Configuration; -using DisplayMagician.GameLibraries.SteamAppInfoParser; -using TsudaKageyu; -using System.Drawing.IconLib; -using System.Drawing.IconLib.Exceptions; using System.Diagnostics; namespace DisplayMagician.GameLibraries { public class SteamGame : Game { - /*private static string SteamLibrary.SteamExe; - private static string SteamLibrary.SteamPath; - private static string _steamConfigVdfFile; - private static string _registrySteamKey = @"SOFTWARE\\Valve\\Steam"; - private static string _registryAppsKey = $@"{_registrySteamKey}\\Apps";*/ private string _gameRegistryKey; private uint _steamGameId; private string _steamGameName; @@ -46,15 +22,6 @@ namespace DisplayMagician.GameLibraries private string _steamGameIconPath; private static List _allInstalledSteamGames = null; - /*private struct SteamAppInfo - { - public uint GameID; - public string GameName; - public List GameExes; - public string GameInstallDir; - public string GameSteamIconPath; - }*/ - static SteamGame() { ServicePointManager.ServerCertificateValidationCallback += @@ -104,47 +71,25 @@ namespace DisplayMagician.GameLibraries public override string Directory { - get => _steamGameExePath; - set => _steamGameExePath = value; + get => _steamGameDir; + set => _steamGameDir = value; } public override bool IsRunning { get { - /*try + int numGameProcesses = 0; + List gameProcesses = Process.GetProcessesByName(_steamGameProcessName).ToList(); + foreach (Process gameProcess in gameProcesses) { - using ( - var key = Registry.CurrentUser.OpenSubKey(_gameRegistryKey, RegistryKeyPermissionCheck.ReadSubTree)) - { - if ((int)key?.GetValue(@"Running", 0) == 1) - { - return true; - } - return false; - } + if (gameProcess.MainModule.FileName.StartsWith(_steamGameExePath)) + numGameProcesses++; } - catch (SecurityException ex) - { - Console.WriteLine($"SteamGame/IsRunning securityexception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); - if (ex.Source != null) - Console.WriteLine("SecurityException source: {0} - Message: {1}", ex.Source, ex.Message); - throw; - } - catch (IOException ex) - { - // Extract some information from this exception, and then - // throw it to the parent method. - Console.WriteLine($"SteamGame/IsRunning ioexception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); - if (ex.Source != null) - Console.WriteLine("IOException source: {0} - Message: {1}", ex.Source, ex.Message); - throw; - }*/ - - bool isRunning = Process.GetProcessesByName(_steamGameProcessName) - .FirstOrDefault(p => p.MainModule.FileName - .StartsWith(ExePath,StringComparison.OrdinalIgnoreCase)) != default(Process); - return isRunning; + if (numGameProcesses > 0) + return true; + else + return false; } } @@ -193,6 +138,7 @@ namespace DisplayMagician.GameLibraries steamGame.Id = Id; steamGame.Name = Name; steamGame.ExePath = ExePath; + steamGame.Directory = Directory; return true; } diff --git a/DisplayMagician/GameLibraries/UplayGame.cs b/DisplayMagician/GameLibraries/UplayGame.cs index 7e0ae9e..59125c0 100644 --- a/DisplayMagician/GameLibraries/UplayGame.cs +++ b/DisplayMagician/GameLibraries/UplayGame.cs @@ -107,47 +107,25 @@ namespace DisplayMagician.GameLibraries public override string Directory { - get => _uplayGameExePath; - set => _uplayGameExePath = value; + get => _uplayGameDir; + set => _uplayGameDir = value; } public override bool IsRunning { get { - /*try + int numGameProcesses = 0; + List gameProcesses = Process.GetProcessesByName(_uplayGameProcessName).ToList(); + foreach (Process gameProcess in gameProcesses) { - using ( - var key = Registry.CurrentUser.OpenSubKey(_gameRegistryKey, RegistryKeyPermissionCheck.ReadSubTree)) - { - if ((int)key?.GetValue(@"Running", 0) == 1) - { - return true; - } - return false; - } + if (gameProcess.MainModule.FileName.StartsWith(_uplayGameExePath)) + numGameProcesses++; } - catch (SecurityException ex) - { - Console.WriteLine($"UplayGame/IsRunning securityexception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); - if (ex.Source != null) - Console.WriteLine("SecurityException source: {0} - Message: {1}", ex.Source, ex.Message); - throw; - } - catch (IOException ex) - { - // Extract some information from this exception, and then - // throw it to the parent method. - Console.WriteLine($"UplayGame/IsRunning ioexception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); - if (ex.Source != null) - Console.WriteLine("IOException source: {0} - Message: {1}", ex.Source, ex.Message); - throw; - }*/ - - bool isRunning = Process.GetProcessesByName(_uplayGameProcessName) - .FirstOrDefault(p => p.MainModule.FileName - .StartsWith(ExePath, StringComparison.OrdinalIgnoreCase)) != default(Process); - return isRunning; + if (numGameProcesses > 0) + return true; + else + return false; } } @@ -196,6 +174,7 @@ namespace DisplayMagician.GameLibraries uplayGame.Id = Id; uplayGame.Name = Name; uplayGame.ExePath = ExePath; + uplayGame.Directory = Directory; return true; } diff --git a/DisplayMagician/Program.cs b/DisplayMagician/Program.cs index b120f57..8d856c1 100644 --- a/DisplayMagician/Program.cs +++ b/DisplayMagician/Program.cs @@ -1,25 +1,18 @@ using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using McMaster.Extensions.CommandLineUtils; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Reflection; -using System.Runtime.CompilerServices; -using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using DisplayMagician.InterProcess; using DisplayMagician.Resources; -using DisplayMagician.GameLibraries; using DisplayMagician.Shared; using DisplayMagician.UIForms; -using System.Net.NetworkInformation; using System.Text.RegularExpressions; using System.Drawing; -using System.Diagnostics.Contracts; namespace DisplayMagician { @@ -60,7 +53,7 @@ namespace DisplayMagician { // Targets where to log to: File and Console string date = DateTime.Now.ToString("yyyyMMdd.HHmmss"); - string AppLogFilename = Path.Combine(Program.AppLogPath, $"DisplayMagician-{date}.log"); + string AppLogFilename = Path.Combine(Program.AppLogPath, $"DisplayMagician.log"); // Create the Shortcut Icon Cache if it doesn't exist so that it's avilable for all the program if (!Directory.Exists(AppLogPath)) @@ -80,9 +73,34 @@ namespace DisplayMagician { }; var logconsole = new NLog.Targets.ConsoleTarget("logconsole"); - // Rules for mapping loggers to targets + // Load the program settings + AppProgramSettings = ProgramSettings.LoadSettings(); + + // Rules for mapping loggers to targets + NLog.LogLevel logLevel = null; + switch (AppProgramSettings.LogLevel) + { + case "Trace": + logLevel = NLog.LogLevel.Trace; + break; + case "Info": + logLevel = NLog.LogLevel.Info; + break; + case "Warn": + logLevel = NLog.LogLevel.Warn; + break; + case "Error": + logLevel = NLog.LogLevel.Error; + break; + case "Debug": + logLevel = NLog.LogLevel.Debug; + break; + default: + logLevel = NLog.LogLevel.Warn; + break; + } config.AddRule(NLog.LogLevel.Info, NLog.LogLevel.Fatal, logconsole); - config.AddRule(NLog.LogLevel.Debug, NLog.LogLevel.Fatal, logfile); + config.AddRule(logLevel, NLog.LogLevel.Fatal, logfile); // Apply config NLog.LogManager.Configuration = config; @@ -103,8 +121,6 @@ namespace DisplayMagician { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); - // Load the program settings - AppProgramSettings = ProgramSettings.LoadSettings(); var app = new CommandLineApplication(); diff --git a/DisplayMagician/ProgramSettings.cs b/DisplayMagician/ProgramSettings.cs index fadd22f..fa41eb6 100644 --- a/DisplayMagician/ProgramSettings.cs +++ b/DisplayMagician/ProgramSettings.cs @@ -5,9 +5,11 @@ using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using NLog; namespace DisplayMagician { + public class ProgramSettings { #region Class Variables @@ -19,6 +21,7 @@ namespace DisplayMagician #region Instance Variables private bool _minimiseOnStart = false; + private string _logLevel = NLog.LogLevel.Warn.ToString(); #endregion #region Class Properties @@ -38,6 +41,45 @@ namespace DisplayMagician } } + public string LogLevel + { + get + { + return _logLevel; + } + set + { + + switch (value.ToLower()) + { + case "trace": + _logLevel = NLog.LogLevel.Trace.ToString(); + break; + case "debug": + _logLevel = NLog.LogLevel.Debug.ToString(); + break; + case "info": + _logLevel = NLog.LogLevel.Info.ToString(); + break; + case "warn": + _logLevel = NLog.LogLevel.Warn.ToString(); + break; + case "Error": + _logLevel = NLog.LogLevel.Error.ToString(); + break; + default: + _logLevel = NLog.LogLevel.Warn.ToString(); + break; + + } + + // Because a value has changed, we need to save the setting + // to remember it for later. + if (_programSettingsLoaded) + SaveSettings(); + } + } + public static Version FileVersion { get => new Version(1, 0, 0); @@ -76,6 +118,11 @@ namespace DisplayMagician } } } + else + { + programSettings = new ProgramSettings(); + programSettings.SaveSettings(); + } // If there isn't any settings in the file then create a new ProgramSettings object if (programSettings == null) diff --git a/DisplayMagician/ShortcutRepository.cs b/DisplayMagician/ShortcutRepository.cs index cabafb9..92b2977 100644 --- a/DisplayMagician/ShortcutRepository.cs +++ b/DisplayMagician/ShortcutRepository.cs @@ -29,6 +29,7 @@ namespace DisplayMagician private static string _shortcutStorageJsonFileName = Path.Combine(AppShortcutStoragePath, $"Shortcuts_{Version.ToString(2)}.json"); private static string uuidV4Regex = @"(?im)^[{(]?[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$"; private static CoreAudioController _audioController = null; + private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); #endregion #region Class Constructors @@ -48,7 +49,8 @@ namespace DisplayMagician } catch (Exception ex) { - Console.WriteLine($"ShortcutItem/Instansiation exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); + //Console.WriteLine($"ShortcutItem/Instansiation exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); + logger.Error(ex, $"ShortcutRepository/Instansiation exception during class construction"); // ignored } @@ -413,6 +415,7 @@ namespace DisplayMagician (bool valid, string reason) = shortcutToUse.IsValid(); if (!valid) { + logger.Error($"ShortcutRepository/RunShortcut error. shortcutToUse isn't valid"); MessageBox.Show( $"Unable to run the shortcut '{shortcutToUse.Name}': {reason}", @"Cannot run the Shortcut", @@ -443,6 +446,7 @@ namespace DisplayMagician if (!Program.ApplyProfile(shortcutToUse.ProfileToUse)) { Console.WriteLine($"ERROR - Cannot apply '{shortcutToUse.ProfileToUse.Name}' Display Profile"); + logger.Error($"ShortcutRepository/RunShortcut cannot apply '{shortcutToUse.ProfileToUse.Name}' Display Profile"); } } @@ -516,7 +520,7 @@ namespace DisplayMagician // This means we need to save the state if the temporaryIcon // is false. // Conversely, if temporaryIcon is true, then we need - // to create a NotifyIncon as MainFOrm isn't running to create + // to create a NotifyIncon as MainForm isn't running to create // one for us already! if (notifyIcon == null) temporaryNotifyIcon = true; @@ -539,6 +543,7 @@ namespace DisplayMagician catch (Exception ex) { Console.WriteLine($"ShortcutRepository/RunShortcut exception: Trying to {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); + logger.Error(ex, $"ShortcutRepository/RunShortcut exception setting NotifyIcon"); // ignored } } @@ -632,6 +637,7 @@ namespace DisplayMagician catch (InvalidOperationException ex) { Console.WriteLine($"ShortcutRepository/RunShortcut exception 2: {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); + logger.Error(ex, $"ShortcutRepository/RunShortcut exception waiting for the monitored process to exit"); processExitCount++; } } @@ -662,6 +668,7 @@ namespace DisplayMagician { address += "/" + shortcutToUse.GameArguments; } + logger.Debug($"ShortcutRepository/RunShortcut Steam launch address is {address}"); // Start the URI Handler to run Steam Console.WriteLine($"Starting Steam Game: {steamGameToRun.Name}"); @@ -695,24 +702,21 @@ namespace DisplayMagician notifyIcon.Text = $"DisplayMagician: Running {steamGameToRun.Name.Substring(0, 41)}..."; Application.DoEvents(); - // Wait 300ms for the game process to spawn - Thread.Sleep(300); - // Now check it's actually started - if (steamGameToRun.IsRunning) - { - // Wait for the game to exit - Console.WriteLine($"Waiting for {steamGameToRun.Name} to exit."); - while (true) - { - if (!steamGameToRun.IsRunning) - { - break; - } - Thread.Sleep(300); + // Wait for the game to exit + Console.WriteLine($"Waiting for {steamGameToRun.Name} to exit."); + logger.Info($"ShortcutRepository/RunShortcut - waiting for Steam Game {steamGameToRun.Name} to exit."); + while (true) + { + if (!steamGameToRun.IsRunning) + { + break; } - Console.WriteLine($"{steamGameToRun.Name} has exited."); + + Thread.Sleep(300); } + Console.WriteLine($"{steamGameToRun.Name} has exited."); + logger.Info($"ShortcutRepository/RunShortcut - Steam Game {steamGameToRun.Name} has exited."); } @@ -729,6 +733,7 @@ namespace DisplayMagician // Prepare to start the steam game using the URI interface // as used by Steam for it's own desktop shortcuts. var address = $"uplay://launch/{uplayGameToRun.Id}"; + logger.Debug($"ShortcutRepository/RunShortcut Uplay launch address is {address}"); if (shortcutToUse.GameArgumentsRequired) { address += "/" + shortcutToUse.GameArguments; @@ -760,28 +765,26 @@ namespace DisplayMagician IPCService.GetInstance().Status = InstanceStatus.OnHold; // Add a status notification icon in the status area - notifyIcon.Text = $"DisplayMagician: Running {uplayGameToRun.Name.Substring(0,41)}..."; + if (uplayGameToRun.Name.Length <= 41) + notifyIcon.Text = $"DisplayMagician: Running {uplayGameToRun.Name}..."; + else + notifyIcon.Text = $"DisplayMagician: Running {uplayGameToRun.Name.Substring(0, 41)}..."; Application.DoEvents(); - // Wait 300ms for the game process to spawn - Thread.Sleep(300); - // Now check it's actually started - if (uplayGameToRun.IsRunning) + // Wait for the game to exit + Console.WriteLine($"Waiting for {uplayGameToRun.Name} to exit."); + logger.Info($"ShortcutRepository/RunShortcut - waiting for Uplay Game {uplayGameToRun.Name} to exit."); + while (true) { - // Wait for the game to exit - Console.WriteLine($"Waiting for {uplayGameToRun.Name} to exit."); - while (true) + if (!uplayGameToRun.IsRunning) { - if (!uplayGameToRun.IsRunning) - { - break; - } - - Thread.Sleep(300); + break; } - Console.WriteLine($"{uplayGameToRun.Name} has exited."); - } + Thread.Sleep(300); + } + Console.WriteLine($"{uplayGameToRun.Name} has exited."); + logger.Info($"ShortcutRepository/RunShortcut - Uplay Game {uplayGameToRun.Name} has exited."); } @@ -884,5 +887,4 @@ namespace DisplayMagician System.Runtime.Serialization.StreamingContext context) : base(info, context) { } } - }