From 3d0b56d8443bc6edcae4c84dac91be4341a5e65c Mon Sep 17 00:00:00 2001 From: Markus Hofknecht Date: Sun, 29 Mar 2020 19:26:45 +0200 Subject: [PATCH] [Feature] CodeBuity&Refactor #49, [Feature] Code review tool #10, Version 0.9.2.13 --- Business/KeyboardInput.cs | 4 +- Business/Program.cs | 4 +- Business/SystemTrayMenu.cs | 52 ++- Config/MenuDefines.cs | 62 ++-- DataClasses/RowData.cs | 348 +++++++++--------- Helpers/KeyboardHook.cs | 13 +- Helpers/Taskbar.cs | 8 +- Helpers/WindowsExplorerSort.cs | 2 +- NativeDllImport/BringWindowToTop.cs | 2 +- NativeDllImport/CreatePopupMenu.cs | 2 +- NativeDllImport/DestroyIcon.cs | 2 +- NativeDllImport/DestroyMenu.cs | 2 +- NativeDllImport/FindExecuteable.cs | 2 +- NativeDllImport/FindWindow.cs | 2 +- NativeDllImport/GetDeviceCaps.cs | 2 +- NativeDllImport/GetIcon.cs | 2 +- NativeDllImport/GetMenuDefaultItem.cs | 2 +- NativeDllImport/RegisterHotKey.cs | 2 +- NativeDllImport/SHAppBarMessage.cs | 2 +- NativeDllImport/SHGetDesktopFolder.cs | 2 +- NativeDllImport/SHGetFileInfo.cs | 2 +- NativeDllImport/SHGetFolderPath.cs | 2 +- NativeDllImport/SetProcessDPIAware.cs | 2 +- NativeDllImport/ShowInactiveTopmost.cs | 2 +- NativeDllImport/ShowWindow.cs | 2 +- NativeDllImport/StrCmpLogicalW.cs | 2 +- NativeDllImport/StrRetToBuf.cs | 2 +- NativeDllImport/TrackPopupMenuEx.cs | 2 +- Properties/AssemblyInfo.cs | 4 +- UserInterface/AboutBox.cs | 76 ++-- UserInterface/AppNotifyIcon.cs | 3 +- UserInterface/FadeForm.cs | 11 +- UserInterface/Menu.cs | 53 +-- .../ShellContextMenu/ShellContextMenu.cs | 24 +- Utilities/AppRestart.cs | 2 + Utilities/DataGridViewExtensions.cs | 4 +- Utilities/File/FileLnk.cs | 2 + Utilities/File/IconReader.cs | 63 ++-- Utilities/FolderOptions.cs | 21 +- Utilities/Log.cs | 52 ++- Utilities/Scaling.cs | 6 +- Utilities/SingleAppInstance.cs | 11 +- 42 files changed, 464 insertions(+), 401 deletions(-) diff --git a/Business/KeyboardInput.cs b/Business/KeyboardInput.cs index 1ab7572..ad15aab 100644 --- a/Business/KeyboardInput.cs +++ b/Business/KeyboardInput.cs @@ -66,9 +66,9 @@ namespace SystemTrayMenu.Handler HotKeyPressed?.Invoke(); } } - catch (Exception ex) + catch (InvalidOperationException ex) { - Log.Error($"key:'{key.ToString()}'", ex); + Log.Error($"key:'{key}'", ex); Properties.Settings.Default.HotKey = string.Empty; Properties.Settings.Default.Save(); MessageBox.Show(ex.Message); diff --git a/Business/Program.cs b/Business/Program.cs index 8055c56..2d5c9f1 100644 --- a/Business/Program.cs +++ b/Business/Program.cs @@ -38,7 +38,9 @@ namespace SystemTrayMenu } } } +#pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) +#pragma warning restore CA1031 // => Represents ThreadException during attached to process { AskUserSendError(ex); } @@ -56,7 +58,7 @@ namespace SystemTrayMenu "Reporting this error will help us make our product better. Press yes to open your standard email app.", "SystemTrayMenu BugSplat", MessageBoxButtons.YesNo) == DialogResult.Yes) { - Process.Start("mailto:" + "markus@hofknecht.eu" + + Log.ProcessStart("mailto:" + "markus@hofknecht.eu" + "?subject=SystemTrayMenu Bug reported" + "&body=" + ex.ToString()); } diff --git a/Business/SystemTrayMenu.cs b/Business/SystemTrayMenu.cs index a0bf4a0..d1e089b 100644 --- a/Business/SystemTrayMenu.cs +++ b/Business/SystemTrayMenu.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; +using System.Security; using System.Windows.Forms; using SystemTrayMenu.DataClasses; using SystemTrayMenu.Handler; @@ -137,7 +138,7 @@ namespace SystemTrayMenu Menus().ToList().ForEach(m => { m.FadeIn(); m.FadeHalf(); }); menus[0].SetTitleColorActive(); menus[0].Activate(); - NativeDllImport.NativeMethods.ForceForegroundWindow(menus[0].Handle); + DllImports.NativeMethods.ForceForegroundWindow(menus[0].Handle); } menuNotifyIcon.OpenLog += Log.OpenLogFile; @@ -355,13 +356,14 @@ namespace SystemTrayMenu directories = Directory.GetDirectories(path); Array.Sort(directories, new WindowsExplorerSort()); } - catch (UnauthorizedAccessException) + catch (UnauthorizedAccessException ex) { - Log.Info($"UnauthorizedAccessException:'{path}'"); + Log.Warn($"path:'{path}'", ex); + menuData.Validity = MenuDataValidity.NoAccess; } - catch (Exception ex) + catch (IOException ex) { - Log.Error($"path:'{path}'", ex); + Log.Warn($"path:'{path}'", ex); } foreach (string directory in directories) @@ -392,32 +394,17 @@ namespace SystemTrayMenu try { - files = Directory.GetFiles(path).Where(p => - !Path.GetFileName(p).Equals("desktop.ini", StringComparison.OrdinalIgnoreCase) && // Windows folder settings, e.g. Win10 "desktop.ini", Win2003 "Desktop.ini" - !Path.GetFileName(p).Equals("thumbs.db", StringComparison.OrdinalIgnoreCase) // Windows thumbnail cache - ).ToArray(); + files = Directory.GetFiles(path); Array.Sort(files, new WindowsExplorerSort()); } - catch (UnauthorizedAccessException) + catch (UnauthorizedAccessException ex) { - Log.Info($"UnauthorizedAccessException:'{path}'"); + Log.Warn($"path:'{path}'", ex); menuData.Validity = MenuDataValidity.NoAccess; } - //catch (PathTooLongException ex) - //{ - - //} - //catch (DirectoryNotFoundException ex) - //{ - - //} - //catch (IOException ex) - //{ - - //} - catch (Exception ex) + catch (IOException ex) { - Log.Error($"path:'{path}'", ex); + Log.Warn($"path:'{path}'", ex); } foreach (string file in files) @@ -478,7 +465,18 @@ namespace SystemTrayMenu } catch (Exception ex) { - Log.Error($"fileName:'{fileName}'", ex); + if (ex is SecurityException || + ex is ArgumentException || + ex is UnauthorizedAccessException || + ex is PathTooLongException || + ex is NotSupportedException) + { + Log.Warn($"fileName:'{fileName}'", ex); + } + else + { + throw; + } } return menuButtonData; @@ -675,7 +673,7 @@ namespace SystemTrayMenu menu.UserClickedOpenFolder += OpenFolder; void OpenFolder() { - Process.Start("explorer.exe", Config.Path); + Log.ProcessStart("explorer.exe", Config.Path); } } menu.Level = menuData.Level; diff --git a/Config/MenuDefines.cs b/Config/MenuDefines.cs index 6519b89..723e6c9 100644 --- a/Config/MenuDefines.cs +++ b/Config/MenuDefines.cs @@ -1,44 +1,46 @@ using System.Collections.Generic; using System.Drawing; +using System.Reflection; namespace SystemTrayMenu { - public static class MenuDefines + internal static class MenuDefines { - public static readonly List Languages = + internal static string NotifyIconText = Assembly.GetExecutingAssembly().GetCustomAttribute().Title; + internal static readonly List Languages = new List() { "en", "de" }; - public static readonly Color File = Color.White; - public static readonly Color Folder = Color.White; - public static readonly Color ColorSelectedItem = AppColors.Blue; - public static readonly Color ColorOpenFolder = AppColors.Green; - public static readonly Color ColorTitleWarning = AppColors.Red; - public static readonly Color ColorTitleSelected = AppColors.Yellow; - public static readonly Color ColorTitleBackground = AppColors.YellowSlightly; - public const int KeySearchInterval = 1000; - public const int MenuRowsHeight = 18; - public const int LengthMax = 37; - public const int Scrollspeed = 4; - public const int WaitMenuOpen = 200; + internal static readonly Color File = Color.White; + internal static readonly Color Folder = Color.White; + internal static readonly Color ColorSelectedItem = AppColors.Blue; + internal static readonly Color ColorOpenFolder = AppColors.Green; + internal static readonly Color ColorTitleWarning = AppColors.Red; + internal static readonly Color ColorTitleSelected = AppColors.Yellow; + internal static readonly Color ColorTitleBackground = AppColors.YellowSlightly; + internal const int KeySearchInterval = 1000; + internal const int MenuRowsHeight = 18; + internal const int LengthMax = 37; + internal const int Scrollspeed = 4; + internal const int WaitMenuOpen = 200; // 60 fps => 1000ms/60fps =~ 16.6ms - public const int IntervalFade = 16; + internal const int IntervalFade = 16; // 60 fps => 1000ms/60fps =~ 16.6ms - public const int IntervalLoad = 16; - public const double OpacityHalfValue = 0.80; - public const double OpacityInStep = 0.20; - public const double OpacityOutStep = 0.05; - public const double OpacityHalfStep = 0.01; - public const int MenusMax = 50; - public const int MaxClicksInQueue = 1; + internal const int IntervalLoad = 16; + internal const double OpacityHalfValue = 0.80; + internal const double OpacityInStep = 0.20; + internal const double OpacityOutStep = 0.05; + internal const double OpacityHalfStep = 0.01; + internal const int MenusMax = 50; + internal const int MaxClicksInQueue = 1; } - public static class AppColors + internal static class AppColors { - public static readonly Color Blue = Color.FromArgb(204, 232, 255); - public static readonly Color BlueSelectedInactive = Color.FromArgb(217, 217, 217); - public static readonly Color Green = Color.FromArgb(194, 245, 222); - public static readonly Color GreenBackgroundInactive = Color.FromArgb(217, 217, 217); - public static readonly Color Red = Color.FromArgb(255, 204, 232); - public static readonly Color Yellow = Color.LightYellow; - public static readonly Color YellowSlightly = Color.Azure; + internal static readonly Color Blue = Color.FromArgb(204, 232, 255); + internal static readonly Color BlueSelectedInactive = Color.FromArgb(217, 217, 217); + internal static readonly Color Green = Color.FromArgb(194, 245, 222); + internal static readonly Color GreenBackgroundInactive = Color.FromArgb(217, 217, 217); + internal static readonly Color Red = Color.FromArgb(255, 204, 232); + internal static readonly Color Yellow = Color.LightYellow; + internal static readonly Color YellowSlightly = Color.Azure; } } \ No newline at end of file diff --git a/DataClasses/RowData.cs b/DataClasses/RowData.cs index 380edac..0a262d5 100644 --- a/DataClasses/RowData.cs +++ b/DataClasses/RowData.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; +using System.Security; using System.Text; using System.Windows.Forms; using SystemTrayMenu.Handler; @@ -15,9 +16,9 @@ using Menu = SystemTrayMenu.UserInterface.Menu; namespace SystemTrayMenu.DataClasses { - public class RowData : IDisposable + internal class RowData : IDisposable { - public event Action OpenMenu; + internal event Action OpenMenu; internal BackgroundWorker Reading = new BackgroundWorker(); internal FileInfo FileInfo; internal Menu SubMenu; @@ -40,140 +41,22 @@ namespace SystemTrayMenu.DataClasses private readonly WaitMenuOpen waitMenuOpen = new WaitMenuOpen(); private bool isDisposed = false; - public RowData() + internal RowData() { Reading.WorkerSupportsCancellation = true; waitMenuOpen.DoOpen += WaitMenuOpen_DoOpen; } - public void SetText(string text) + internal void SetText(string text) { - if (text != null && text.Length > MenuDefines.LengthMax) + if (text.Length > MenuDefines.LengthMax) { text = $"{text.Substring(0, MenuDefines.LengthMax)}..."; } Text = text; } - private bool SetLnk(ref bool isLnkDirectory, - ref string resolvedLnkPath) - { - bool handled = false; - resolvedLnkPath = LnkHelper.ResolveShortcut(TargetFilePath); - if (LnkHelper.IsDirectory(resolvedLnkPath)) - { - Icon = IconReader.GetFolderIcon(TargetFilePath, - IconReader.FolderType.Open, true); - handled = true; - isLnkDirectory = true; - } - else if (string.IsNullOrEmpty(resolvedLnkPath)) - { - ResolvedFileNotFound = true; - Log.Info($"Resolve *.LNK '{TargetFilePath}' has no icon"); -#warning [Feature] Resolve network root #48, start here - } - else - { - IWshShell shell = new WshShell(); - IWshShortcut lnk = shell.CreateShortcut(TargetFilePath) - as IWshShortcut; - Arguments = lnk.Arguments; - WorkingDirectory = lnk.WorkingDirectory; - string iconLocation = lnk.IconLocation; - if (iconLocation.Length > 2) - { - iconLocation = iconLocation.Substring(0, - iconLocation.Length - 2); - if (System.IO.File.Exists(iconLocation)) - { - try - { - Icon = Icon.ExtractAssociatedIcon(iconLocation); - handled = true; - } - catch (Exception ex) - { - Log.Error($"iconLocation:'{iconLocation}'", ex); - } - } - } - - TargetFilePath = resolvedLnkPath; - } - - SetText(Path.GetFileNameWithoutExtension(TargetFilePathOrig)); - - return handled; - } - - private bool SetUrl() - { - bool handled = false; - string iconFile = string.Empty; - try - { - FileIni file = new FileIni(TargetFilePath); - iconFile = file.Value("IconFile", string.Empty); - if (string.IsNullOrEmpty(iconFile)) - { - string browserPath = FileUrl.GetDefaultBrowserPath(); - if (string.IsNullOrEmpty(browserPath)) - { - Log.Info($"Resolve *.URL '{TargetFilePath}'" + - $"No default browser found!"); - } - else - { - Icon = IconReader.GetFileIconWithCache(browserPath, false); - handled = true; - } - } - else if (System.IO.File.Exists(iconFile)) - { - Icon = Icon.ExtractAssociatedIcon(iconFile); - handled = true; - } - else - { - Log.Info($"Resolve *.URL '{TargetFilePath}' has no icon"); - } - } - catch (Exception ex) - { - Log.Error($"TargetFilePath:'{TargetFilePath}', " + - $"iconFile:'{iconFile}'", ex); - } - - SetText($"{FileInfo.Name.Substring(0, FileInfo.Name.Length - 4)}"); - - return handled; - } - - private bool SetSln() - { - bool handled = false; - StringBuilder executable = new StringBuilder(1024); - try - { - NativeDllImport.NativeMethods.Shell32FindExecutable(TargetFilePath, string.Empty, executable); - // icon = IconReader.GetFileIcon(executable, false); - // e.g. VS 2019 icon, need another icom in imagelist - List extractedIcons = IconHelper.ExtractAllIcons( - executable.ToString()); - Icon = extractedIcons.Last(); - handled = true; - } - catch (Exception ex) - { - Log.Error($"TargetFilePath:'{TargetFilePath}', " + - $"executable:'{executable.ToString()}'", ex); - } - - return handled; - } - - public void SetData(RowData data, DataGridView dgv) + internal void SetData(RowData data, DataGridView dgv) { data.RowIndex = dgv.Rows.Add(); DataGridViewRow row = dgv.Rows[data.RowIndex]; @@ -202,7 +85,7 @@ namespace SystemTrayMenu.DataClasses row.Tag = data; } - public bool ReadIcon(bool isDirectory, ref string resolvedLnkPath) + internal bool ReadIcon(bool isDirectory, ref string resolvedLnkPath) { bool isLnkDirectory = false; @@ -252,7 +135,18 @@ namespace SystemTrayMenu.DataClasses } catch (Exception ex) { - Log.Error($"TargetFilePath:'{TargetFilePath}'", ex); + if (ex is SecurityException || + ex is ArgumentException || + ex is UnauthorizedAccessException || + ex is PathTooLongException || + ex is NotSupportedException) + { + Log.Warn($"path:'{TargetFilePath}'", ex); + } + else + { + throw; + } } } } @@ -260,7 +154,148 @@ namespace SystemTrayMenu.DataClasses return isLnkDirectory; } - public void MouseDown(DataGridView dgv, MouseEventArgs e) + + private bool SetLnk(ref bool isLnkDirectory, + ref string resolvedLnkPath) + { + bool handled = false; + resolvedLnkPath = LnkHelper.ResolveShortcut(TargetFilePath); + if (LnkHelper.IsDirectory(resolvedLnkPath)) + { + Icon = IconReader.GetFolderIcon(TargetFilePath, + IconReader.FolderType.Open, true); + handled = true; + isLnkDirectory = true; + } + else if (string.IsNullOrEmpty(resolvedLnkPath)) + { + ResolvedFileNotFound = true; + Log.Info($"Resolve *.LNK '{TargetFilePath}' has no icon"); +#warning [Feature] Resolve network root #48, start here + } + else + { + IWshShell shell = new WshShell(); + IWshShortcut lnk = shell.CreateShortcut(TargetFilePath) + as IWshShortcut; + Arguments = lnk.Arguments; + WorkingDirectory = lnk.WorkingDirectory; + string iconLocation = lnk.IconLocation; + if (iconLocation.Length > 2) + { + iconLocation = iconLocation.Substring(0, + iconLocation.Length - 2); + if (System.IO.File.Exists(iconLocation)) + { + try + { + Icon = Icon.ExtractAssociatedIcon(iconLocation); + handled = true; + } + catch (ArgumentException ex) + { + Log.Error($"iconLocation:'{iconLocation}'", ex); + } + } + } + + TargetFilePath = resolvedLnkPath; + } + + SetText(Path.GetFileNameWithoutExtension(TargetFilePathOrig)); + + return handled; + } + + private bool SetUrl() + { + bool handled = false; + string iconFile = string.Empty; + try + { + FileIni file = new FileIni(TargetFilePath); + iconFile = file.Value("IconFile", string.Empty); + if (string.IsNullOrEmpty(iconFile)) + { + string browserPath = FileUrl.GetDefaultBrowserPath(); + if (string.IsNullOrEmpty(browserPath)) + { + Log.Info($"Resolve *.URL '{TargetFilePath}'" + + $"No default browser found!"); + } + else + { + Icon = IconReader.GetFileIconWithCache(browserPath, false); + handled = true; + } + } + else if (System.IO.File.Exists(iconFile)) + { + Icon = Icon.ExtractAssociatedIcon(iconFile); + handled = true; + } + else + { + Log.Info($"Resolve *.URL '{TargetFilePath}' has no icon"); + } + } + catch (Exception ex) + { + if (ex is SecurityException || + ex is ArgumentException || + ex is UnauthorizedAccessException || + ex is PathTooLongException || + ex is NotSupportedException) + { + Log.Warn($"path:'{TargetFilePath}', " + + $"iconFile:'{iconFile}'", ex); + } + else + { + throw; + } + } + + SetText($"{FileInfo.Name.Substring(0, FileInfo.Name.Length - 4)}"); + + return handled; + } + + private bool SetSln() + { + bool handled = false; + StringBuilder executable = new StringBuilder(1024); + try + { + DllImports.NativeMethods.Shell32FindExecutable(TargetFilePath, string.Empty, executable); + // icon = IconReader.GetFileIcon(executable, false); + // e.g. VS 2019 icon, need another icom in imagelist + List extractedIcons = IconHelper.ExtractAllIcons( + executable.ToString()); + Icon = extractedIcons.Last(); + handled = true; + } + catch (Exception ex) + { + if (ex is SecurityException || + ex is ArgumentException || + ex is UnauthorizedAccessException || + ex is PathTooLongException || + ex is NotSupportedException) + { + Log.Warn($"path:'{TargetFilePath}', " + + $"executable:'{executable}'", ex); + } + else + { + throw; + } + } + + return handled; + } + + internal void MouseDown(DataGridView dgv, MouseEventArgs e) { if (ContainsMenu) { @@ -290,10 +325,9 @@ namespace SystemTrayMenu.DataClasses p.Start(); }; } - catch (Exception ex) + catch (Win32Exception ex) { - Log.Error($"TargetFilePath:'{ TargetFilePath}', " + - $"=>FileNotFound?", ex); + Log.Warn($"path:'{TargetFilePath}'", ex); MessageBox.Show(ex.Message); } } @@ -301,35 +335,29 @@ namespace SystemTrayMenu.DataClasses if (e != null && e.Button == MouseButtons.Right && FileInfo != null && + dgv != null && dgv.Rows.Count > RowIndex) { IsContextMenuOpen = true; IsSelected = true; dgv.Rows[RowIndex].Selected = true; - try + ShellContextMenu ctxMnu = new ShellContextMenu(); + Point location = dgv.FindForm().Location; + Point point = new Point( + e.X + location.X + dgv.Location.X, + e.Y + location.Y + dgv.Location.Y); + if (ContainsMenu) { - ShellContextMenu ctxMnu = new ShellContextMenu(); - Point location = dgv.FindForm().Location; - Point point = new Point( - e.X + location.X + dgv.Location.X, - e.Y + location.Y + dgv.Location.Y); - if (ContainsMenu) - { - DirectoryInfo[] dir = new DirectoryInfo[1]; - dir[0] = new DirectoryInfo(TargetFilePathOrig); - ctxMnu.ShowContextMenu(dir, point); - } - else - { - FileInfo[] arrFI = new FileInfo[1]; - arrFI[0] = new FileInfo(TargetFilePathOrig); - ctxMnu.ShowContextMenu(arrFI, point); - } + DirectoryInfo[] dir = new DirectoryInfo[1]; + dir[0] = new DirectoryInfo(TargetFilePathOrig); + ctxMnu.ShowContextMenu(dir, point); } - catch (Exception ex) + else { - MessageBox.Show(ex.ToString() + TargetFilePath); + FileInfo[] arrFI = new FileInfo[1]; + arrFI[0] = new FileInfo(TargetFilePathOrig); + ctxMnu.ShowContextMenu(arrFI, point); } if (!dgv.IsDisposed) @@ -342,30 +370,20 @@ namespace SystemTrayMenu.DataClasses } } - public void DoubleClick() + internal void DoubleClick() { if (ContainsMenu) { - try - { - Process.Start("explorer.exe", TargetFilePath); - } - catch (Exception ex) - { - Log.Error($"TargetFilePath:'{TargetFilePath}', " + - $"=>DirectoryNotFound?", ex); - ex = new DirectoryNotFoundException(); - MessageBox.Show(ex.Message); - } + Log.ProcessStart("explorer.exe", TargetFilePath); } } - public void MenuLoaded() + internal void MenuLoaded() { waitMenuOpen.MenuLoaded(); } - public void StartMenuOpener() + internal void StartMenuOpener() { if (ContainsMenu) { @@ -382,7 +400,7 @@ namespace SystemTrayMenu.DataClasses } } - public void StopLoadMenuAndStartWaitToOpenIt() + internal void StopLoadMenuAndStartWaitToOpenIt() { if (ContainsMenu) { diff --git a/Helpers/KeyboardHook.cs b/Helpers/KeyboardHook.cs index b241dd0..7bb4dd9 100644 --- a/Helpers/KeyboardHook.cs +++ b/Helpers/KeyboardHook.cs @@ -61,10 +61,7 @@ namespace SystemTrayMenu.Helper // register the event of the inner native window. _window.KeyPressed += delegate (object sender, KeyPressedEventArgs args) { - if (KeyPressed != null) - { - KeyPressed(this, args); - } + KeyPressed?.Invoke(this, args); }; } @@ -75,13 +72,13 @@ namespace SystemTrayMenu.Helper /// The key itself that is associated with the hot key. internal void RegisterHotKey(KeyboardHookModifierKeys modifier, Keys key) { - // increment the counter. _currentId = _currentId + 1; - // register the hot key. - if (!NativeDllImport.NativeMethods.User32RegisterHotKey(_window.Handle, _currentId, (uint)modifier, (uint)key)) + if (!DllImports.NativeMethods.User32RegisterHotKey(_window.Handle, _currentId, (uint)modifier, (uint)key)) { +#pragma warning disable CA1303 // Do not pass literals as localized parameters throw new InvalidOperationException("Couldn’t register the hot key."); +#pragma warning restore CA1303 //=> Exceptions not translated in logfile => OK } } @@ -97,7 +94,7 @@ namespace SystemTrayMenu.Helper // unregister all the registered hot keys. for (int i = _currentId; i > 0; i--) { - NativeDllImport.NativeMethods.User32UnregisterHotKey(_window.Handle, i); + DllImports.NativeMethods.User32UnregisterHotKey(_window.Handle, i); } // dispose the inner native window. diff --git a/Helpers/Taskbar.cs b/Helpers/Taskbar.cs index cf1f55c..17f6d78 100644 --- a/Helpers/Taskbar.cs +++ b/Helpers/Taskbar.cs @@ -1,7 +1,7 @@ using System; using System.Drawing; using System.Runtime.InteropServices; -using static SystemTrayMenu.NativeDllImport.NativeMethods; +using static SystemTrayMenu.DllImports.NativeMethods; namespace SystemTrayMenu.Helper.Taskbar { @@ -45,14 +45,14 @@ namespace SystemTrayMenu.Helper.Taskbar public Taskbar() { - IntPtr taskbarHandle = NativeDllImport.NativeMethods.User32FindWindow(Taskbar.ClassName, null); + IntPtr taskbarHandle = DllImports.NativeMethods.User32FindWindow(Taskbar.ClassName, null); APPBARDATA data = new APPBARDATA { cbSize = (uint)Marshal.SizeOf(typeof(APPBARDATA)), hWnd = taskbarHandle }; - IntPtr result = NativeDllImport.NativeMethods.Shell32SHAppBarMessage(ABM.GetTaskbarPos, ref data); + IntPtr result = DllImports.NativeMethods.Shell32SHAppBarMessage(ABM.GetTaskbarPos, ref data); if (result == IntPtr.Zero) { //throw new InvalidOperationException(); @@ -64,7 +64,7 @@ namespace SystemTrayMenu.Helper.Taskbar Bounds = Rectangle.FromLTRB(data.rc.left, data.rc.top, data.rc.right, data.rc.bottom); data.cbSize = (uint)Marshal.SizeOf(typeof(APPBARDATA)); - result = NativeDllImport.NativeMethods.Shell32SHAppBarMessage(ABM.GetState, ref data); + result = DllImports.NativeMethods.Shell32SHAppBarMessage(ABM.GetState, ref data); int state = result.ToInt32(); AlwaysOnTop = (state & ABS.AlwaysOnTop) == ABS.AlwaysOnTop; AutoHide = (state & ABS.Autohide) == ABS.Autohide; diff --git a/Helpers/WindowsExplorerSort.cs b/Helpers/WindowsExplorerSort.cs index 7c2d8d8..1b49190 100644 --- a/Helpers/WindowsExplorerSort.cs +++ b/Helpers/WindowsExplorerSort.cs @@ -6,7 +6,7 @@ namespace SystemTrayMenu.Helper { public int Compare(string x, string y) { - return NativeDllImport.NativeMethods.ShlwapiStrCmpLogicalW(x, y); + return DllImports.NativeMethods.ShlwapiStrCmpLogicalW(x, y); } } } diff --git a/NativeDllImport/BringWindowToTop.cs b/NativeDllImport/BringWindowToTop.cs index 170ce7b..9e37730 100644 --- a/NativeDllImport/BringWindowToTop.cs +++ b/NativeDllImport/BringWindowToTop.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/CreatePopupMenu.cs b/NativeDllImport/CreatePopupMenu.cs index 4f39b7f..0df9623 100644 --- a/NativeDllImport/CreatePopupMenu.cs +++ b/NativeDllImport/CreatePopupMenu.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/DestroyIcon.cs b/NativeDllImport/DestroyIcon.cs index c39c571..6198dde 100644 --- a/NativeDllImport/DestroyIcon.cs +++ b/NativeDllImport/DestroyIcon.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/DestroyMenu.cs b/NativeDllImport/DestroyMenu.cs index 32f2ccc..d908d23 100644 --- a/NativeDllImport/DestroyMenu.cs +++ b/NativeDllImport/DestroyMenu.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/FindExecuteable.cs b/NativeDllImport/FindExecuteable.cs index 864360b..2bc5698 100644 --- a/NativeDllImport/FindExecuteable.cs +++ b/NativeDllImport/FindExecuteable.cs @@ -1,7 +1,7 @@ using System.Runtime.InteropServices; using System.Text; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/FindWindow.cs b/NativeDllImport/FindWindow.cs index 990c00f..1727498 100644 --- a/NativeDllImport/FindWindow.cs +++ b/NativeDllImport/FindWindow.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/GetDeviceCaps.cs b/NativeDllImport/GetDeviceCaps.cs index 0a584da..7861662 100644 --- a/NativeDllImport/GetDeviceCaps.cs +++ b/NativeDllImport/GetDeviceCaps.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/GetIcon.cs b/NativeDllImport/GetIcon.cs index 438b54b..a0e3c9d 100644 --- a/NativeDllImport/GetIcon.cs +++ b/NativeDllImport/GetIcon.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/GetMenuDefaultItem.cs b/NativeDllImport/GetMenuDefaultItem.cs index 192fd33..f9fd5d1 100644 --- a/NativeDllImport/GetMenuDefaultItem.cs +++ b/NativeDllImport/GetMenuDefaultItem.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/RegisterHotKey.cs b/NativeDllImport/RegisterHotKey.cs index b307308..8c32c23 100644 --- a/NativeDllImport/RegisterHotKey.cs +++ b/NativeDllImport/RegisterHotKey.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/SHAppBarMessage.cs b/NativeDllImport/SHAppBarMessage.cs index f030a77..2a5f3a7 100644 --- a/NativeDllImport/SHAppBarMessage.cs +++ b/NativeDllImport/SHAppBarMessage.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/SHGetDesktopFolder.cs b/NativeDllImport/SHGetDesktopFolder.cs index 92ca9a2..7d88cf1 100644 --- a/NativeDllImport/SHGetDesktopFolder.cs +++ b/NativeDllImport/SHGetDesktopFolder.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/SHGetFileInfo.cs b/NativeDllImport/SHGetFileInfo.cs index c7b2894..e72ddad 100644 --- a/NativeDllImport/SHGetFileInfo.cs +++ b/NativeDllImport/SHGetFileInfo.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/SHGetFolderPath.cs b/NativeDllImport/SHGetFolderPath.cs index 81f5bd1..688e24a 100644 --- a/NativeDllImport/SHGetFolderPath.cs +++ b/NativeDllImport/SHGetFolderPath.cs @@ -2,7 +2,7 @@ using System.Runtime.InteropServices; using System.Text; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/SetProcessDPIAware.cs b/NativeDllImport/SetProcessDPIAware.cs index 683c89d..91c9b3b 100644 --- a/NativeDllImport/SetProcessDPIAware.cs +++ b/NativeDllImport/SetProcessDPIAware.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/ShowInactiveTopmost.cs b/NativeDllImport/ShowInactiveTopmost.cs index d4276a3..aaf7dff 100644 --- a/NativeDllImport/ShowInactiveTopmost.cs +++ b/NativeDllImport/ShowInactiveTopmost.cs @@ -1,7 +1,7 @@ using System.Runtime.InteropServices; using System.Windows.Forms; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/ShowWindow.cs b/NativeDllImport/ShowWindow.cs index ebc5d9f..e0e4739 100644 --- a/NativeDllImport/ShowWindow.cs +++ b/NativeDllImport/ShowWindow.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/StrCmpLogicalW.cs b/NativeDllImport/StrCmpLogicalW.cs index 90bdee9..cc746b5 100644 --- a/NativeDllImport/StrCmpLogicalW.cs +++ b/NativeDllImport/StrCmpLogicalW.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/StrRetToBuf.cs b/NativeDllImport/StrRetToBuf.cs index 933a3e9..7096b79 100644 --- a/NativeDllImport/StrRetToBuf.cs +++ b/NativeDllImport/StrRetToBuf.cs @@ -2,7 +2,7 @@ using System.Runtime.InteropServices; using System.Text; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/NativeDllImport/TrackPopupMenuEx.cs b/NativeDllImport/TrackPopupMenuEx.cs index 41ebd40..2e39eab 100644 --- a/NativeDllImport/TrackPopupMenuEx.cs +++ b/NativeDllImport/TrackPopupMenuEx.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -namespace SystemTrayMenu.NativeDllImport +namespace SystemTrayMenu.DllImports { public static partial class NativeMethods { diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index a90c7ae..18c2682 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -35,5 +35,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.9.2.12")] -[assembly: AssemblyFileVersion("0.9.2.12")] +[assembly: AssemblyVersion("0.9.2.13")] +[assembly: AssemblyFileVersion("0.9.2.13")] diff --git a/UserInterface/AboutBox.cs b/UserInterface/AboutBox.cs index fe11f85..21d7cc2 100644 --- a/UserInterface/AboutBox.cs +++ b/UserInterface/AboutBox.cs @@ -1,10 +1,12 @@ using Microsoft.Win32; using System; using System.Collections.Specialized; +using System.Diagnostics; using System.Drawing; using System.Globalization; using System.IO; using System.Reflection; +using System.Security; using System.Text.RegularExpressions; using System.Windows.Forms; using SystemTrayMenu.Utilities; @@ -193,11 +195,7 @@ namespace SystemTrayMenu.UserInterface DateTime assemblyLastWriteTime = DateTime.MaxValue; if (!string.IsNullOrEmpty(a.Location)) { - try - { - assemblyLastWriteTime = File.GetLastWriteTime(a.Location); - } - catch (Exception) { } + assemblyLastWriteTime = File.GetLastWriteTime(a.Location); } return assemblyLastWriteTime; @@ -355,22 +353,15 @@ namespace SystemTrayMenu.UserInterface { nvc.Add("Location", "(not supported)"); } - // version - try + + string version = "(unknown)"; + AssemblyName assemblyName = a.GetName(); + if (assemblyName.Version != null && + (assemblyName.Version.Major != 0 || assemblyName.Version.Minor != 0)) { - if (a.GetName().Version.Major == 0 && a.GetName().Version.Minor == 0) - { - nvc.Add("Version", "(unknown)"); - } - else - { - nvc.Add("Version", a.GetName().Version.ToString()); - } - } - catch (Exception) - { - nvc.Add("Version", "(unknown)"); + version = a.GetName().Version.ToString(); } + nvc.Add("Version", version); nvc.Add("FullName", a.FullName); @@ -388,7 +379,19 @@ namespace SystemTrayMenu.UserInterface RegistryKey rk = Registry.LocalMachine.OpenSubKey(KeyName); strSysInfoPath = (string)rk.GetValue(SubKeyRef, string.Empty); } - catch (Exception) { } + catch (Exception ex) + { + if (ex is SecurityException || + ex is UnauthorizedAccessException || + ex is IOException) + { + Log.Warn($"KeyName:'{KeyName}' SubKeyRef:'{SubKeyRef}'", ex); + } + else + { + throw; + } + } return strSysInfoPath; } @@ -414,19 +417,7 @@ namespace SystemTrayMenu.UserInterface return; } - try - { - System.Diagnostics.Process.Start(strSysInfoPath); - } - catch (Exception) - { - MessageBox.Show("System Information is unavailable at this time." + - Environment.NewLine + - Environment.NewLine + - "(couldn't launch '" + strSysInfoPath + "')", - Text, MessageBoxButtons.OK, MessageBoxIcon.Stop); - } - + Log.ProcessStart(strSysInfoPath); } // @@ -641,14 +632,9 @@ namespace SystemTrayMenu.UserInterface _ExecutingAssemblyName = Assembly.GetExecutingAssembly().GetName().Name; _CallingAssemblyName = Assembly.GetCallingAssembly().GetName().Name; - try - { - // for web hosted apps, GetEntryAssembly = nothing - _EntryAssemblyName = Assembly.GetEntryAssembly().GetName().Name; - } - catch (Exception) - { - } + + // for web hosted apps, GetEntryAssembly = nothing + _EntryAssemblyName = Assembly.GetEntryAssembly().GetName().Name; _MinWindowHeight = AppCopyrightLabel.Top + AppCopyrightLabel.Height + buttonOk.Height + 30; @@ -753,13 +739,7 @@ namespace SystemTrayMenu.UserInterface // private void MoreRichTextBox_LinkClicked(object sender, LinkClickedEventArgs e) { - try - { - System.Diagnostics.Process.Start(e.LinkText); - } - catch (Exception) - { - } + Log.ProcessStart(e.LinkText); } // diff --git a/UserInterface/AppNotifyIcon.cs b/UserInterface/AppNotifyIcon.cs index 8dc6dd3..782c3b7 100644 --- a/UserInterface/AppNotifyIcon.cs +++ b/UserInterface/AppNotifyIcon.cs @@ -34,8 +34,7 @@ namespace SystemTrayMenu.UserInterface notifyIcon.Icon = bitmapsLoading.First(); load.Tick += Load_Tick; load.Interval = MenuDefines.IntervalLoad; - - notifyIcon.Text = "SystemTrayMenu"; + notifyIcon.Text = MenuDefines.NotifyIconText; notifyIcon.Visible = true; notifyIcon.Icon = R.SystemTrayMenu; AppContextMenu contextMenus = new AppContextMenu(); diff --git a/UserInterface/FadeForm.cs b/UserInterface/FadeForm.cs index ad08c78..9c3160f 100644 --- a/UserInterface/FadeForm.cs +++ b/UserInterface/FadeForm.cs @@ -13,11 +13,13 @@ namespace SystemTrayMenu.UserInterface private readonly Timer timerFadeOut = new Timer(); private readonly Timer timerFadeHalf = new Timer(); private readonly Form form = null; + private readonly bool disposeForm = false; private bool stopFadeInByHalf = false; - public FadeForm(Form form) + public FadeForm(Form form, bool disposeForm = false) { this.form = form; + this.disposeForm = disposeForm; timerFadeIn.Interval = MenuDefines.IntervalFade; timerFadeOut.Interval = MenuDefines.IntervalFade; timerFadeHalf.Interval = MenuDefines.IntervalFade; @@ -39,7 +41,10 @@ namespace SystemTrayMenu.UserInterface timerFadeIn.Dispose(); timerFadeOut.Dispose(); timerFadeHalf.Dispose(); - //form.Dispose(); recursiv + if (disposeForm) + { + form.Dispose(); + } } } @@ -79,7 +84,7 @@ namespace SystemTrayMenu.UserInterface } else { - NativeDllImport.NativeMethods.User32ShowInactiveTopmost(form); + DllImports.NativeMethods.User32ShowInactiveTopmost(form); timerFadeOut.Stop(); timerFadeIn.Start(); } diff --git a/UserInterface/Menu.cs b/UserInterface/Menu.cs index fa1cdf1..ed8da24 100644 --- a/UserInterface/Menu.cs +++ b/UserInterface/Menu.cs @@ -10,15 +10,15 @@ using EventHandler = SystemTrayMenu.Helper.EventHandler; namespace SystemTrayMenu.UserInterface { - public partial class Menu : Form + internal partial class Menu : Form { - public new event EventHandler MouseWheel; - public event EventHandler Deactivated; - public event EventHandler UserClickedOpenFolder; + internal new event EventHandler MouseWheel; + internal event EventHandler Deactivated; + internal event EventHandler UserClickedOpenFolder; - public event Action CmdKeyProcessed; + internal event Action CmdKeyProcessed; - public enum Type + internal enum Type { Main, Sub, @@ -27,20 +27,21 @@ namespace SystemTrayMenu.UserInterface MaxReached } - public bool IsFadingIn => FadeForm.IsFadingIn; + internal bool IsFadingIn => FadeForm.IsFadingIn; - public bool IsFadingOut => FadeForm.IsFadingOut; + internal bool IsFadingOut => FadeForm.IsFadingOut; internal int Level = 0; private readonly FadeForm FadeForm = null; private bool autoResizeRowsDone = false; - public enum MenuType { Default, DisposedFake }; + internal enum MenuType { Default, DisposedFake }; - public Menu(MenuType menuType = MenuType.Default) + internal Menu(MenuType menuType = MenuType.Default) { FadeForm = new FadeForm(this); + InitializeComponent(); SetDoubleBuffer(dgv, true); @@ -68,20 +69,20 @@ namespace SystemTrayMenu.UserInterface System.Globalization.CultureInfo.InvariantCulture); } - public void SetTypeSub() + internal void SetTypeSub() { SetType(Type.Sub); } - public void SetTypeEmpty() + internal void SetTypeEmpty() { SetType(Type.Empty); } - public void SetTypeNoAccess() + internal void SetTypeNoAccess() { SetType(Type.NoAccess); } - public void SetType(Type type) + internal void SetType(Type type) { switch (type) { @@ -110,18 +111,18 @@ namespace SystemTrayMenu.UserInterface } } - public bool IsVisible() + internal bool IsVisible() { return Visible; } - public bool IsActive(Form activeForm) + internal bool IsActive(Form activeForm) { bool isActive = (this == activeForm); return isActive; } - public bool IsMouseOn(Point mousePosition) + internal bool IsMouseOn(Point mousePosition) { bool isMouseOn = Visible && Opacity >= MenuDefines.OpacityHalfValue && ClientRectangle.Contains( @@ -129,12 +130,12 @@ namespace SystemTrayMenu.UserInterface return isMouseOn; } - public DataGridView GetDataGridView() + internal DataGridView GetDataGridView() { return dgv; } - public void SetTitle(string title) + internal void SetTitle(string title) { if (!string.IsNullOrEmpty(title)) { @@ -146,22 +147,22 @@ namespace SystemTrayMenu.UserInterface } } - public void FadeIn() + internal void FadeIn() { FadeForm.FadeIn(); } - public void FadeHalf() + internal void FadeHalf() { FadeForm.FadeHalf(); } - public void FadeOut() + internal void FadeOut() { FadeForm.FadeOut(); } - public void AdjustLocationAndSize(Screen screen) + internal void AdjustLocationAndSize(Screen screen) { if (screen != null) { @@ -184,7 +185,7 @@ namespace SystemTrayMenu.UserInterface } } - public void AdjustLocationAndSize(int heightMax, Menu menuPredecessor) + internal void AdjustLocationAndSize(int heightMax, Menu menuPredecessor) { DataGridViewElementStates states = DataGridViewElementStates.None; if (!autoResizeRowsDone) @@ -279,12 +280,12 @@ namespace SystemTrayMenu.UserInterface Deactivated?.Invoke(); } - public void SetTitleColorDeactive() + internal void SetTitleColorDeactive() { labelTitle.ForeColor = Color.LightGray; } - public void SetTitleColorActive() + internal void SetTitleColorActive() { labelTitle.ForeColor = Color.Black; } diff --git a/UserInterface/ShellContextMenu/ShellContextMenu.cs b/UserInterface/ShellContextMenu/ShellContextMenu.cs index d1b3f8c..3356687 100644 --- a/UserInterface/ShellContextMenu/ShellContextMenu.cs +++ b/UserInterface/ShellContextMenu/ShellContextMenu.cs @@ -235,10 +235,12 @@ namespace SystemTrayMenu.Utilities if (null == _oDesktopFolder) { // Get desktop IShellFolder - int nResult = NativeDllImport.NativeMethods.Shell32SHGetDesktopFolder(out pUnkownDesktopFolder); + int nResult = DllImports.NativeMethods.Shell32SHGetDesktopFolder(out pUnkownDesktopFolder); if (S_OK != nResult) { +#pragma warning disable CA1303 // Do not pass literals as localized parameters throw new ShellContextMenuException("Failed to get the desktop shell folder"); +#pragma warning restore CA1303 //=> Exceptions not translated in logfile => OK } _oDesktopFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(pUnkownDesktopFolder, typeof(IShellFolder)); } @@ -277,7 +279,7 @@ namespace SystemTrayMenu.Utilities Marshal.WriteInt32(pStrRet, 0, 0); nResult = _oDesktopFolder.GetDisplayNameOf(pPIDL, SHGNO.FORPARSING, pStrRet); StringBuilder strFolder = new StringBuilder(MAX_PATH); - _ = NativeDllImport.NativeMethods.ShlwapiStrRetToBuf(pStrRet, pPIDL, strFolder, MAX_PATH); + _ = DllImports.NativeMethods.ShlwapiStrRetToBuf(pStrRet, pPIDL, strFolder, MAX_PATH); Marshal.FreeCoTaskMem(pStrRet); pStrRet = IntPtr.Zero; _strParentFolder = strFolder.ToString(); @@ -423,7 +425,7 @@ namespace SystemTrayMenu.Utilities return; } - pMenu = NativeDllImport.NativeMethods.User32CreatePopupMenu(); + pMenu = DllImports.NativeMethods.User32CreatePopupMenu(); int nResult = _oContextMenu.QueryContextMenu( pMenu, @@ -433,13 +435,13 @@ namespace SystemTrayMenu.Utilities CMF.DEFAULTONLY | ((Control.ModifierKeys & Keys.Shift) != 0 ? CMF.EXTENDEDVERBS : 0)); - uint nDefaultCmd = (uint)NativeDllImport.NativeMethods.User32GetMenuDefaultItem(pMenu, false, 0); + uint nDefaultCmd = (uint)DllImports.NativeMethods.User32GetMenuDefaultItem(pMenu, false, 0); if (nDefaultCmd >= CMD_FIRST) { InvokeCommand(_oContextMenu, nDefaultCmd, arrFI[0].DirectoryName, Control.MousePosition); } - NativeDllImport.NativeMethods.User32DestroyMenu(pMenu); + DllImports.NativeMethods.User32DestroyMenu(pMenu); pMenu = IntPtr.Zero; } catch @@ -450,7 +452,7 @@ namespace SystemTrayMenu.Utilities { if (pMenu != IntPtr.Zero) { - NativeDllImport.NativeMethods.User32DestroyMenu(pMenu); + DllImports.NativeMethods.User32DestroyMenu(pMenu); } ReleaseAll(); } @@ -516,7 +518,7 @@ namespace SystemTrayMenu.Utilities return; } - pMenu = NativeDllImport.NativeMethods.User32CreatePopupMenu(); + pMenu = DllImports.NativeMethods.User32CreatePopupMenu(); int nResult = _oContextMenu.QueryContextMenu( pMenu, @@ -535,15 +537,15 @@ namespace SystemTrayMenu.Utilities //hook.Install(); - uint nSelected = NativeDllImport.NativeMethods.User32TrackPopupMenuEx( + uint nSelected = DllImports.NativeMethods.User32TrackPopupMenuEx( pMenu, - NativeDllImport.NativeMethods.TPM.RETURNCMD, + DllImports.NativeMethods.TPM.RETURNCMD, pointScreen.X, pointScreen.Y, Handle, IntPtr.Zero); - NativeDllImport.NativeMethods.User32DestroyMenu(pMenu); + DllImports.NativeMethods.User32DestroyMenu(pMenu); pMenu = IntPtr.Zero; if (nSelected != 0) @@ -560,7 +562,7 @@ namespace SystemTrayMenu.Utilities //hook.Uninstall(); if (pMenu != IntPtr.Zero) { - NativeDllImport.NativeMethods.User32DestroyMenu(pMenu); + DllImports.NativeMethods.User32DestroyMenu(pMenu); } if (iContextMenuPtr != IntPtr.Zero) diff --git a/Utilities/AppRestart.cs b/Utilities/AppRestart.cs index 328818a..7ff535d 100644 --- a/Utilities/AppRestart.cs +++ b/Utilities/AppRestart.cs @@ -2,6 +2,7 @@ using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; +using System.Windows.Forms; using EventHandler = SystemTrayMenu.Helper.EventHandler; namespace SystemTrayMenu.Utilities @@ -17,6 +18,7 @@ namespace SystemTrayMenu.Utilities Log.Close(); Process.Start(Assembly.GetExecutingAssembly(). ManifestModule.FullyQualifiedName); + Application.Exit(); } [MethodImpl(MethodImplOptions.NoInlining)] diff --git a/Utilities/DataGridViewExtensions.cs b/Utilities/DataGridViewExtensions.cs index 107c0c9..a66de5c 100644 --- a/Utilities/DataGridViewExtensions.cs +++ b/Utilities/DataGridViewExtensions.cs @@ -4,9 +4,9 @@ using System.Windows.Forms; namespace SystemTrayMenu.Utilities { - public static class DataGridViewExtensions + internal static class DataGridViewExtensions { - public static void FastAutoSizeColumns(this DataGridView dgv) + internal static void FastAutoSizeColumns(this DataGridView dgv) { System.Collections.Generic.IEnumerable rows = dgv.Rows .Cast(); diff --git a/Utilities/File/FileLnk.cs b/Utilities/File/FileLnk.cs index db08480..a1bc1df 100644 --- a/Utilities/File/FileLnk.cs +++ b/Utilities/File/FileLnk.cs @@ -160,7 +160,9 @@ namespace SystemTrayMenu.Utilities public static string ResolveShortcut(string filename) { ShellLink link = new ShellLink(); +#pragma warning disable CA2010 // Always consume the value returned by methods marked with PreserveSigAttribute ((IPersistFile)link).Load(filename, STGM_READ); +#pragma warning restore CA2010 // => Has no returned value => OK StringBuilder sb = new StringBuilder(MAX_PATH); WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); ((IShellLinkW)link).GetPath(sb, sb.Capacity, out data, 0); diff --git a/Utilities/File/IconReader.cs b/Utilities/File/IconReader.cs index 49b1abe..27db559 100644 --- a/Utilities/File/IconReader.cs +++ b/Utilities/File/IconReader.cs @@ -70,29 +70,29 @@ namespace SystemTrayMenu.Utilities IconSize size = IconSize.Small) { Icon icon = null; - NativeDllImport.NativeMethods.SHFILEINFO shfi = new NativeDllImport.NativeMethods.SHFILEINFO(); - uint flags = NativeDllImport.NativeMethods.ShgfiIcon | NativeDllImport.NativeMethods.ShgfiSYSICONINDEX; + DllImports.NativeMethods.SHFILEINFO shfi = new DllImports.NativeMethods.SHFILEINFO(); + uint flags = DllImports.NativeMethods.ShgfiIcon | DllImports.NativeMethods.ShgfiSYSICONINDEX; //MH: Removed, otherwise wrong icon // | Shell32.SHGFI_USEFILEATTRIBUTES ; if (true == linkOverlay) { - flags += NativeDllImport.NativeMethods.ShgfiLINKOVERLAY; + flags += DllImports.NativeMethods.ShgfiLINKOVERLAY; } /* Check the size specified for return. */ if (IconSize.Small == size) { - flags += NativeDllImport.NativeMethods.ShgfiSMALLICON; + flags += DllImports.NativeMethods.ShgfiSMALLICON; } else { - flags += NativeDllImport.NativeMethods.ShgfiLARGEICON; + flags += DllImports.NativeMethods.ShgfiLARGEICON; } - IntPtr hImageList = NativeDllImport.NativeMethods.Shell32SHGetFileInfo(filePath, - NativeDllImport.NativeMethods.FileAttributeNormal, + IntPtr hImageList = DllImports.NativeMethods.Shell32SHGetFileInfo(filePath, + DllImports.NativeMethods.FileAttributeNormal, ref shfi, (uint)System.Runtime.InteropServices.Marshal.SizeOf(shfi), flags); @@ -106,26 +106,18 @@ namespace SystemTrayMenu.Utilities else { // Get icon from .ink without overlay - hIcon = NativeDllImport.NativeMethods.ImageList_GetIcon(hImageList, shfi.iIcon, NativeDllImport.NativeMethods.IldTransparent); + hIcon = DllImports.NativeMethods.ImageList_GetIcon(hImageList, shfi.iIcon, DllImports.NativeMethods.IldTransparent); } - try - { - // Copy (clone) the returned icon to a new object, thus allowing us to clean-up properly - icon = (Icon)Icon.FromHandle(hIcon).Clone(); - } - catch (Exception ex) - { - Log.Error($"filePath:'{filePath}'", ex); - } + icon = (Icon)Icon.FromHandle(hIcon).Clone(); // Cleanup if (!linkOverlay) { - NativeDllImport.NativeMethods.User32DestroyIcon(hIcon); + DllImports.NativeMethods.User32DestroyIcon(hIcon); } - NativeDllImport.NativeMethods.User32DestroyIcon(shfi.hIcon); + DllImports.NativeMethods.User32DestroyIcon(shfi.hIcon); } return icon; @@ -141,50 +133,39 @@ namespace SystemTrayMenu.Utilities //uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_USEFILEATTRIBUTES; //MH: Removed SHGFI_USEFILEATTRIBUTES, otherwise was wrong folder icon - uint flags = NativeDllImport.NativeMethods.ShgfiIcon; // | Shell32.SHGFI_USEFILEATTRIBUTES; + uint flags = DllImports.NativeMethods.ShgfiIcon; // | Shell32.SHGFI_USEFILEATTRIBUTES; if (true == linkOverlay) { - flags += NativeDllImport.NativeMethods.ShgfiLINKOVERLAY; + flags += DllImports.NativeMethods.ShgfiLINKOVERLAY; } if (FolderType.Open == folderType) { - flags += NativeDllImport.NativeMethods.ShgfiOPENICON; + flags += DllImports.NativeMethods.ShgfiOPENICON; } if (IconSize.Small == size) { - flags += NativeDllImport.NativeMethods.ShgfiSMALLICON; + flags += DllImports.NativeMethods.ShgfiSMALLICON; } else { - flags += NativeDllImport.NativeMethods.ShgfiLARGEICON; + flags += DllImports.NativeMethods.ShgfiLARGEICON; } // Get the folder icon - NativeDllImport.NativeMethods.SHFILEINFO shfi = new NativeDllImport.NativeMethods.SHFILEINFO(); - IntPtr Success = NativeDllImport.NativeMethods.Shell32SHGetFileInfo(directoryPath, - NativeDllImport.NativeMethods.FileAttributeDirectory, + DllImports.NativeMethods.SHFILEINFO shfi = new DllImports.NativeMethods.SHFILEINFO(); + IntPtr Success = DllImports.NativeMethods.Shell32SHGetFileInfo(directoryPath, + DllImports.NativeMethods.FileAttributeDirectory, ref shfi, (uint)Marshal.SizeOf(shfi), flags); if (Success != IntPtr.Zero) // got valid handle? { - try - { - Icon.FromHandle(shfi.hIcon); // Load the icon from an HICON handle - - // Now clone the icon, so that it can be successfully stored in an ImageList - icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone(); - } - catch (Exception ex) - { - Log.Error($"directoryPath:'{directoryPath}'", ex); - } - - // Cleanup - NativeDllImport.NativeMethods.User32DestroyIcon(shfi.hIcon); + Icon.FromHandle(shfi.hIcon); + icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone(); + DllImports.NativeMethods.User32DestroyIcon(shfi.hIcon); } return icon; diff --git a/Utilities/FolderOptions.cs b/Utilities/FolderOptions.cs index d1b4aa2..26afc4c 100644 --- a/Utilities/FolderOptions.cs +++ b/Utilities/FolderOptions.cs @@ -1,6 +1,8 @@ using Shell32; using System; using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; namespace SystemTrayMenu.Utilities { @@ -30,7 +32,24 @@ namespace SystemTrayMenu.Utilities } catch (Exception ex) { - Log.Error("Get Shell COM instance failed", ex); + if (ex is ArgumentException || + ex is NotSupportedException || + ex is TargetInvocationException || + ex is MethodAccessException || + ex is MemberAccessException || + ex is InvalidComObjectException || + ex is MissingMethodException || + ex is COMException || + ex is TypeLoadException) + { +#pragma warning disable CA1303 // Do not pass literals as localized parameters + Log.Warn("Get Shell COM instance failed", ex); +#pragma warning restore CA1303 //=> Exceptions not translated in logfile => OK + } + else + { + throw; + } } } diff --git a/Utilities/Log.cs b/Utilities/Log.cs index 3b1d025..e328159 100644 --- a/Utilities/Log.cs +++ b/Utilities/Log.cs @@ -1,8 +1,10 @@ using Clearcove.Logging; using System; +using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Reflection; +using System.Windows.Forms; namespace SystemTrayMenu.Utilities { @@ -19,9 +21,15 @@ namespace SystemTrayMenu.Utilities log.Info(message); } - //internal static void Warn(string message) + internal static void Warn(string message, Exception ex) + { + log.Warn($"{message}{Environment.NewLine}" + + $"{ex.ToString()}"); + } + + //internal static void Debug(string message) //{ - // log.Warn($"{message}{Environment.NewLine}" + + // log.Debug($"{message}{Environment.NewLine}" + // $"{Environment.StackTrace.ToString()}"); //} @@ -40,7 +48,7 @@ namespace SystemTrayMenu.Utilities internal static void OpenLogFile() { - Process.Start(GetLogFilePath()); + ProcessStart(GetLogFilePath()); } internal static void WriteApplicationRuns() @@ -56,5 +64,43 @@ namespace SystemTrayMenu.Utilities { Logger.ShutDown(); } + + internal static void ProcessStart(string fileName, string arguments = null) + { + if (!string.IsNullOrEmpty(arguments) && + !Directory.Exists(arguments)) + { + Exception ex = new DirectoryNotFoundException(); + Warn($"path:'{arguments}'", ex); + MessageBox.Show(ex.Message); + } + else + { + try + { + //if (!string.IsNullOrEmpty(arguments)) + //{ + Process.Start(fileName, arguments); + //} + //else + //{ + // Process.Start(fileName); + //} + } + catch (Exception ex) + { + if (ex is FileNotFoundException || + ex is Win32Exception) + { + Warn($"fileName:'{fileName}' arguments:'{arguments}'", ex); + MessageBox.Show(ex.Message); + } + else + { + throw; + } + } + } + } } } diff --git a/Utilities/Scaling.cs b/Utilities/Scaling.cs index 8943107..2dcf4ce 100644 --- a/Utilities/Scaling.cs +++ b/Utilities/Scaling.cs @@ -21,7 +21,7 @@ namespace SystemTrayMenu.Utilities { if (Environment.OSVersion.Version.Major >= 6) { - NativeDllImport.NativeMethods.User32SetProcessDPIAware(); + DllImports.NativeMethods.User32SetProcessDPIAware(); } } } @@ -30,9 +30,9 @@ namespace SystemTrayMenu.Utilities { Graphics g = Graphics.FromHwnd(IntPtr.Zero); IntPtr desktop = g.GetHdc(); - int LogicalScreenHeight = NativeDllImport.NativeMethods.Gdi32GetDeviceCaps( + int LogicalScreenHeight = DllImports.NativeMethods.Gdi32GetDeviceCaps( desktop, (int)DeviceCap.VERTRES); - int PhysicalScreenHeight = NativeDllImport.NativeMethods.Gdi32GetDeviceCaps( + int PhysicalScreenHeight = DllImports.NativeMethods.Gdi32GetDeviceCaps( desktop, (int)DeviceCap.DESKTOPVERTRES); Factor = PhysicalScreenHeight / (float)LogicalScreenHeight; } diff --git a/Utilities/SingleAppInstance.cs b/Utilities/SingleAppInstance.cs index 697fb3c..67683e5 100644 --- a/Utilities/SingleAppInstance.cs +++ b/Utilities/SingleAppInstance.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Diagnostics; using System.Linq; @@ -29,7 +30,15 @@ namespace SystemTrayMenu.Utilities } catch (Exception ex) { - Log.Error("Run as single instance failed", ex); + if (ex is Win32Exception || + ex is SystemException) + { + Log.Error("Run as single instance failed", ex); + } + else + { + throw; + } } return killedAProcess;