From ba636414c0f08af9aa65eda6478f8420e4e32f91 Mon Sep 17 00:00:00 2001 From: Terry MacDonald Date: Sun, 7 Feb 2021 14:42:17 +1300 Subject: [PATCH] Improve exception handling of existing ex Added logger instances for DisplayMagicianShared functions. Also added logger debug commands to all exceptions with existing ex objects. --- DisplayMagician/GameLibraries/SteamGame.cs | 3 +- DisplayMagician/GameLibraries/SteamLibrary.cs | 8 +- DisplayMagician/GameLibraries/UplayGame.cs | 5 +- DisplayMagician/GameLibraries/UplayLibrary.cs | 8 +- DisplayMagician/ShortcutItem.cs | 8 +- DisplayMagician/UIForms/ProfileAdaptor.cs | 3 + DisplayMagician/UIForms/ShortcutAdaptor.cs | 5 +- .../DisplayMagicianShared.csproj | 6 +- DisplayMagicianShared/Logger.cs | 99 +++++++++++++++++++ .../NVIDIA/SurroundTopologyDisplay.cs | 3 + DisplayMagicianShared/ProfileRepository.cs | 9 +- .../DisplayMagicianShellExtension.csproj | 4 + 12 files changed, 141 insertions(+), 20 deletions(-) create mode 100644 DisplayMagicianShared/Logger.cs diff --git a/DisplayMagician/GameLibraries/SteamGame.cs b/DisplayMagician/GameLibraries/SteamGame.cs index 0ab3d7a..ab9788a 100644 --- a/DisplayMagician/GameLibraries/SteamGame.cs +++ b/DisplayMagician/GameLibraries/SteamGame.cs @@ -20,7 +20,7 @@ namespace DisplayMagician.GameLibraries private string _steamGameExe; private string _steamGameProcessName; private string _steamGameIconPath; - //private static List _allInstalledSteamGames = null; + private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); static SteamGame() { @@ -90,6 +90,7 @@ namespace DisplayMagician.GameLibraries } catch (Exception ex) { + logger.Debug(ex, $"SteamGame/IsRunning: Accessing Process.MainModule caused exception. Trying GameUtils.GetMainModuleFilepath instead"); if (GameUtils.GetMainModuleFilepath(gameProcess.Id).StartsWith(_steamGameExePath)) numGameProcesses++; } diff --git a/DisplayMagician/GameLibraries/SteamLibrary.cs b/DisplayMagician/GameLibraries/SteamLibrary.cs index 20ac4b8..9d1a305 100644 --- a/DisplayMagician/GameLibraries/SteamLibrary.cs +++ b/DisplayMagician/GameLibraries/SteamLibrary.cs @@ -54,19 +54,19 @@ namespace DisplayMagician.GameLibraries } catch (SecurityException ex) { - logger.Warn("The user does not have the permissions required to read the Steam registry key."); + logger.Warn(ex,"The user does not have the permissions required to read the Steam registry key."); } catch (ObjectDisposedException ex) { - logger.Warn("The Microsoft.Win32.RegistryKey is closed when trying to access theSteam registry key (closed keys cannot be accessed)."); + logger.Warn(ex, "The Microsoft.Win32.RegistryKey is closed when trying to access theSteam registry key (closed keys cannot be accessed)."); } catch (IOException ex) { - logger.Warn("The Steam registry key has been marked for deletion so we cannot access the value during the SteamLibrary check."); + logger.Warn(ex, "The Steam registry key has been marked for deletion so we cannot access the value during the SteamLibrary check."); } catch (UnauthorizedAccessException ex) { - logger.Warn("The user does not have the necessary registry rights to check whether Steam is installed."); + logger.Warn(ex, "The user does not have the necessary registry rights to check whether Steam is installed."); } } #endregion diff --git a/DisplayMagician/GameLibraries/UplayGame.cs b/DisplayMagician/GameLibraries/UplayGame.cs index b546e39..908ed41 100644 --- a/DisplayMagician/GameLibraries/UplayGame.cs +++ b/DisplayMagician/GameLibraries/UplayGame.cs @@ -18,7 +18,7 @@ namespace DisplayMagician.GameLibraries private string _uplayGameExe; private string _uplayGameProcessName; private string _uplayGameIconPath; - //private static List _allInstalledUplayGames = null; + private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); static UplayGame() { @@ -91,6 +91,9 @@ namespace DisplayMagician.GameLibraries } catch (Exception ex) { + logger.Debug(ex, $"UplayGame/IsRunning: Accessing Process.MainModule caused exception. Trying GameUtils.GetMainModuleFilepath instead"); + // If there is a race condition where MainModule isn't available, then we + // instead try the much slower GetMainModuleFilepath (which does the same thing) if (GameUtils.GetMainModuleFilepath(gameProcess.Id).StartsWith(_uplayGameExePath)) numGameProcesses++; } diff --git a/DisplayMagician/GameLibraries/UplayLibrary.cs b/DisplayMagician/GameLibraries/UplayLibrary.cs index ce27238..921ad42 100644 --- a/DisplayMagician/GameLibraries/UplayLibrary.cs +++ b/DisplayMagician/GameLibraries/UplayLibrary.cs @@ -59,19 +59,19 @@ namespace DisplayMagician.GameLibraries } catch (SecurityException ex) { - logger.Warn("The user does not have the permissions required to read the Uplay InstallDir registry key."); + logger.Warn(ex, "UplayLibrary/UplayLibrary: The user does not have the permissions required to read the Uplay InstallDir registry key."); } catch(ObjectDisposedException ex) { - logger.Warn("The Microsoft.Win32.RegistryKey is closed when trying to access the Uplay InstallDir registry key (closed keys cannot be accessed)."); + logger.Warn(ex, "UplayLibrary/UplayLibrary: The Microsoft.Win32.RegistryKey is closed when trying to access the Uplay InstallDir registry key (closed keys cannot be accessed)."); } catch (IOException ex) { - logger.Warn("The Uplay InstallDir registry key has been marked for deletion so we cannot access the value dueing the UplayLibrary check."); + logger.Warn(ex, "UplayLibrary/UplayLibrary: The Uplay InstallDir registry key has been marked for deletion so we cannot access the value dueing the UplayLibrary check."); } catch (UnauthorizedAccessException ex) { - logger.Warn("The user does not have the necessary registry rights to check whether Uplay is installed."); + logger.Warn(ex, "UplayLibrary/UplayLibrary: The user does not have the necessary registry rights to check whether Uplay is installed."); } } #endregion diff --git a/DisplayMagician/ShortcutItem.cs b/DisplayMagician/ShortcutItem.cs index a055a98..2fc15d9 100644 --- a/DisplayMagician/ShortcutItem.cs +++ b/DisplayMagician/ShortcutItem.cs @@ -62,9 +62,6 @@ namespace DisplayMagician public class ShortcutItem : IComparable { - //private static List _allSavedShortcuts = new List(); - //private MultiIcon _shortcutIcon, _originalIcon = null; - //private string _savedShortcutIconCacheFilename = ""; private string _profileUuid = ""; private ProfileItem _profileToUse; private string _uuid = ""; @@ -102,6 +99,7 @@ namespace DisplayMagician [JsonIgnore] public string _savedShortcutIconCacheFilename; #pragma warning restore CS3008 // Identifier is not CLS-compliant + private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); public ShortcutItem() { @@ -2109,8 +2107,8 @@ namespace DisplayMagician } catch (Exception ex) { - Console.WriteLine($"ShortcutItem/CreateShortcut exception (deleting old shortcut)"); - + logger.Warn(ex, $"ShortcutItem/CreateShortcut: Execption while creating desktop shortcut!"); + // Clean up a failed attempt if (System.IO.File.Exists(shortcutFileName)) { diff --git a/DisplayMagician/UIForms/ProfileAdaptor.cs b/DisplayMagician/UIForms/ProfileAdaptor.cs index a8292bf..8a7b277 100644 --- a/DisplayMagician/UIForms/ProfileAdaptor.cs +++ b/DisplayMagician/UIForms/ProfileAdaptor.cs @@ -19,6 +19,7 @@ namespace DisplayMagician.UIForms { private bool disposed; + private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); /// /// Initializes a new instance of the class. @@ -170,6 +171,7 @@ namespace DisplayMagician.UIForms catch (Exception ex) { // catch the System.Drawing.Image exception created while accessing the Size + logger.Debug(ex, "ProfileAdaptor/GetDetails: System.Drawing.Image exception caused while trying to get the ProfileBitmap Size as an Integer."); } } @@ -187,6 +189,7 @@ namespace DisplayMagician.UIForms catch (Exception ex) { // catch the System.Drawing.Image exception created while accessing the Size + logger.Debug(ex, "ProfileAdaptor/GetDetails: System.Drawing.Image exception caused while trying to get the ProfileBitmap Size as a Float."); } } string name = profileToUse.Name; diff --git a/DisplayMagician/UIForms/ShortcutAdaptor.cs b/DisplayMagician/UIForms/ShortcutAdaptor.cs index 3aef14a..c92b6b7 100644 --- a/DisplayMagician/UIForms/ShortcutAdaptor.cs +++ b/DisplayMagician/UIForms/ShortcutAdaptor.cs @@ -17,6 +17,7 @@ namespace DisplayMagician.UIForms { private bool disposed; + private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); /// /// Initializes a new instance of the class. @@ -145,7 +146,7 @@ namespace DisplayMagician.UIForms catch (Exception ex) { // catch the System.Drawing.Image exception created while accessing the Size - mySize = new Size(256, 256); + logger.Debug(ex, "ShortcutAdaptor/GetDetails: System.Drawing.Image exception caused while trying to get the ProfileBitmap Size as an Integer."); } } @@ -163,7 +164,7 @@ namespace DisplayMagician.UIForms catch (Exception ex) { // catch the System.Drawing.Image exception created while accessing the Size - mySizeF = new SizeF(256, 256); + logger.Debug(ex, "ShortcutAdaptor/GetDetails: System.Drawing.Image exception caused while trying to get the ProfileBitmap Size as a Float."); } } diff --git a/DisplayMagicianShared/DisplayMagicianShared.csproj b/DisplayMagicianShared/DisplayMagicianShared.csproj index 969713d..d788104 100644 --- a/DisplayMagicianShared/DisplayMagicianShared.csproj +++ b/DisplayMagicianShared/DisplayMagicianShared.csproj @@ -7,7 +7,7 @@ {1CACDA43-01C7-4CD4-BF6E-9421A29510FC} Library Properties - DisplayMagician.Shared + DisplayMagicianShared DisplayMagician.Shared v4.8 512 @@ -51,6 +51,7 @@ + True True @@ -112,6 +113,9 @@ 12.0.3 + + 4.7.7 + 0.7.2.63 diff --git a/DisplayMagicianShared/Logger.cs b/DisplayMagicianShared/Logger.cs new file mode 100644 index 0000000..9a20e4a --- /dev/null +++ b/DisplayMagicianShared/Logger.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace DisplayMagicianShared +{ + class Logger + { + + internal static string AppDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DisplayMagician"); + internal static string AppLogPath = Path.Combine(AppDataPath, $"Logs"); + internal static string AppSettingsFile = Path.Combine(AppDataPath, $"Settings_1.0.json"); + public static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + + static Logger() + { + // Prepare NLog for logging + var config = new NLog.Config.LoggingConfiguration(); + + // Targets where to log to: File and Console + //string date = DateTime.Now.ToString("yyyyMMdd.HHmmss"); + string AppLogFilename = Path.Combine(AppLogPath, $"DisplayMagicianShared.log"); + + // Create the Logging Dir if it doesn't exist so that it's avilable for all + // parts of the program to use + if (!Directory.Exists(AppLogPath)) + { + try + { + Directory.CreateDirectory(AppLogPath); + } + catch (Exception ex) + { + Console.WriteLine($"Logger/Logger: Exception creating logging directory {AppLogPath} - {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); + } + } + + var logfile = new NLog.Targets.FileTarget("logfile") + { + FileName = AppLogFilename + }; + var logconsole = new NLog.Targets.ConsoleTarget("logconsole"); + + // Figure out what logging level we're at in the main app + // and set that up here + NLog.LogLevel logLevel = NLog.LogLevel.Info; + + // Look for the LogLevel line and use that + // "LogLevel": "Warn" + if (File.Exists(AppLogFilename)) + { + + using (StreamReader sr = File.OpenText(AppLogFilename)) + { + string s = ""; + while ((s = sr.ReadLine()) != null) + { + string pattern = @"\s?""LogLevel""\s?\:\s?""(Trace|Info|Warn|Error|Debug|Fatal)"""; + MatchCollection matches = Regex.Matches(s, pattern); + + switch (matches[1].Value) + { + 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; + } + break; + } + } + + } + config.AddRule(NLog.LogLevel.Info, NLog.LogLevel.Fatal, logconsole); + config.AddRule(logLevel, NLog.LogLevel.Fatal, logfile); + + // Apply config + NLog.LogManager.Configuration = config; + } + + } +} diff --git a/DisplayMagicianShared/NVIDIA/SurroundTopologyDisplay.cs b/DisplayMagicianShared/NVIDIA/SurroundTopologyDisplay.cs index a25259d..67f66e0 100644 --- a/DisplayMagicianShared/NVIDIA/SurroundTopologyDisplay.cs +++ b/DisplayMagicianShared/NVIDIA/SurroundTopologyDisplay.cs @@ -9,11 +9,13 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; using NvAPIWrapper.Mosaic; using NvAPIWrapper.Native.Exceptions; +using DisplayMagicianShared; namespace DisplayMagicianShared.NVIDIA { public class SurroundTopologyDisplay { + public SurroundTopologyDisplay(GridTopologyDisplay display) { DisplayId = display.DisplayDevice.DisplayId; @@ -34,6 +36,7 @@ namespace DisplayMagicianShared.NVIDIA catch (NVIDIAApiException ex) { //Debug.WriteLine($"SurroundTopologyDisplay/NVIDIAApiException exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); + Logger.logger.Debug(ex, $"SurroundTopologyDisplay/NVIDIAApiException: Accessing NvAPIWRapper ReadEDDIDData caused exception. Setting generic DisplayID instead"); // If we hit here then we cannot find the DisplayName from the EDID Data from the GPU // So we just make one up using the DisplayID DisplayName = $"Display #{DisplayId}"; diff --git a/DisplayMagicianShared/ProfileRepository.cs b/DisplayMagicianShared/ProfileRepository.cs index 72702bb..55c2028 100644 --- a/DisplayMagicianShared/ProfileRepository.cs +++ b/DisplayMagicianShared/ProfileRepository.cs @@ -549,10 +549,13 @@ namespace DisplayMagicianShared isNvidia = true; } catch (Exception ex) - { } + { + Logger.logger.Debug(ex, "ProfileRepository/GenerateProfileDisplayIdentifiers: Attemped to get GetPhysicalCPUs through NvAPIWrapper library but got exception."); + } if (isNvidia && myPhysicalGPUs != null && myPhysicalGPUs.Length > 0) { + Logger.logger.Debug("ProfileRepository/GenerateProfileDisplayIdentifiers: Was able to GetPhysicalCPUs through NvAPIWrapper library."); foreach (NvAPIWrapper.GPU.PhysicalGPU myPhysicalGPU in myPhysicalGPUs) { @@ -683,7 +686,9 @@ namespace DisplayMagicianShared isNvidia = true; } catch (Exception ex) - { } + { + Logger.logger.Debug(ex, "ProfileRepository/GenerateAllAvailableDisplayIdentifiers: Attemped to get GetPhysicalCPUs through NvAPIWrapper library but got exception."); + } if (isNvidia && myPhysicalGPUs != null && myPhysicalGPUs.Length > 0) { diff --git a/DisplayMagicianShellExtension/DisplayMagicianShellExtension.csproj b/DisplayMagicianShellExtension/DisplayMagicianShellExtension.csproj index cbedbf3..1d84c35 100644 --- a/DisplayMagicianShellExtension/DisplayMagicianShellExtension.csproj +++ b/DisplayMagicianShellExtension/DisplayMagicianShellExtension.csproj @@ -23,6 +23,7 @@ 4 true false + DisplayMagicianShellExtension.ruleset pdbonly @@ -31,6 +32,8 @@ TRACE prompt 4 + DisplayMagicianShellExtension.ruleset + true Resources\DisplayMagician.ico @@ -88,6 +91,7 @@ .editorconfig +