From 12f133827e7c33d3eb3c552b5c2638884114733e Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 11 Jan 2022 13:33:22 +0100 Subject: [PATCH 01/32] Import files from old PR #15329 --- .../Components/NativeMethods.cs | 37 +++- .../Components/OpenWindows.cs | 2 +- .../Components/SearchController.cs | 2 +- .../Components/Window.cs | 200 ++++++++++-------- .../Components/WindowProcess.cs | 183 ++++++++++++++++ .../Microsoft.Plugin.WindowWalker/Main.cs | 3 +- 6 files changed, 335 insertions(+), 92 deletions(-) create mode 100644 src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs index c158e51f1a8a..31d04a44b0a6 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs @@ -249,7 +249,7 @@ public enum DwmNCRenderingPolicy } /// - /// Window attribute + /// DWM window attribute (Windows 7 and earlier: The values between ExcludedFromPeek and Last aren't supported.) /// [Flags] public enum DwmWindowAttribute @@ -266,9 +266,32 @@ public enum DwmWindowAttribute HasIconicBitmap, DisallowPeek, ExcludedFromPeek, + Cloak, + Cloaked, + FreezeRepresentation, + PassiveUpdateMode, + UseHostbackdropbrush, + UseImmersiveDarkMode, + WindowCornerPreference, + BorderColor, + CaptionColor, + TextColor, + VisibelFrameBorderTickness, Last, } + /// + /// Flags for describing the window cloak state (Windows 7 and earlier: This value is not supported.) + /// + [Flags] + public enum DwmWindowCloakState + { + None = 0, + CloakedApp = 1, + CloakedShell = 2, + CloakedInherited = 4, + } + /// /// Flags for accessing the process in trying to get icon for the process /// @@ -869,7 +892,7 @@ public enum ExtendedWindowStyles : uint [DllImport("user32.dll", SetLastError = true, BestFitMapping = false)] public static extern IntPtr GetProp(IntPtr hWnd, string lpString); - [DllImport("kernel32.dll")] + [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId); [DllImport("dwmapi.dll", EntryPoint = "#113", CallingConvention = CallingConvention.StdCall)] @@ -890,5 +913,15 @@ public enum ExtendedWindowStyles : uint [DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int msg, int wParam); + + public static int GetLastWin32Error() + { + return Marshal.GetLastWin32Error(); + } + + public static int GetSizeOfUInt() + { + return Marshal.SizeOf(typeof(uint)); + } } } diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs index af135a238d78..81ead455a9cf 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs @@ -93,7 +93,7 @@ public bool WindowEnumerationCallBack(IntPtr hwnd, IntPtr lParam) if (newWindow.IsWindow && newWindow.Visible && newWindow.IsOwner && (!newWindow.IsToolWindow || newWindow.IsAppWindow) && !newWindow.TaskListDeleted && - newWindow.ClassName != "Windows.UI.Core.CoreWindow" && newWindow.ProcessName != _powerLauncherExe) + newWindow.ClassName != "Windows.UI.Core.CoreWindow" && newWindow.ProcessInfo.Name != _powerLauncherExe) { windows.Add(newWindow); } diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs index 16c6cc237c48..826311de0738 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs @@ -151,7 +151,7 @@ private List FuzzySearchOpenWindows(List openWindows) foreach (var window in openWindows) { var titleMatch = FuzzyMatching.FindBestFuzzyMatch(window.Title, searchString.SearchText); - var processMatch = FuzzyMatching.FindBestFuzzyMatch(window.ProcessName, searchString.SearchText); + var processMatch = FuzzyMatching.FindBestFuzzyMatch(window.ProcessInfo.Name, searchString.SearchText); if ((titleMatch.Count != 0 || processMatch.Count != 0) && window.Title.Length != 0) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs index 59bf6471e3f2..a8e25f19b946 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs @@ -19,20 +19,20 @@ namespace Microsoft.Plugin.WindowWalker.Components public class Window { /// - /// Maximum size of a file name + /// The handle to the window /// - private const int MaximumFileNameLength = 1000; + private readonly IntPtr hwnd; /// /// The list of owners of a window so that we don't have to /// constantly query for the process owning a specific window /// - private static readonly Dictionary _handlesToProcessCache = new Dictionary(); + private static readonly Dictionary _handlesToProcessCache = new Dictionary(); /// - /// The handle to the window + /// An instance of that contains the process information for the window /// - private readonly IntPtr hwnd; + private readonly WindowProcess processInfo; /// /// Gets the title of the window (the string displayed at the top of the window) @@ -68,63 +68,12 @@ public IntPtr Hwnd get { return hwnd; } } - public uint ProcessID { get; set; } - /// - /// Gets returns the name of the process + /// Gets the object of with the process information of the window /// - public string ProcessName + public WindowProcess ProcessInfo { - get - { - lock (_handlesToProcessCache) - { - if (_handlesToProcessCache.Count > 7000) - { - Debug.Print("Clearing Process Cache because it's size is " + _handlesToProcessCache.Count); - _handlesToProcessCache.Clear(); - } - - if (!_handlesToProcessCache.ContainsKey(Hwnd)) - { - var processName = GetProcessNameFromWindowHandle(Hwnd); - - if (processName.Length != 0) - { - _handlesToProcessCache.Add( - Hwnd, - processName.ToString().Split('\\').Reverse().ToArray()[0]); - } - else - { - _handlesToProcessCache.Add(Hwnd, string.Empty); - } - } - - if (_handlesToProcessCache[hwnd].ToUpperInvariant() == "APPLICATIONFRAMEHOST.EXE") - { - new Task(() => - { - NativeMethods.CallBackPtr callbackptr = new NativeMethods.CallBackPtr((IntPtr hwnd, IntPtr lParam) => - { - var childProcessId = GetProcessIDFromWindowHandle(hwnd); - if (childProcessId != ProcessID) - { - _handlesToProcessCache[Hwnd] = GetProcessNameFromWindowHandle(hwnd); - return false; - } - else - { - return true; - } - }); - _ = NativeMethods.EnumChildWindows(Hwnd, callbackptr, 0); - }).Start(); - } - - return _handlesToProcessCache[hwnd]; - } - } + get { return processInfo; } } /// @@ -134,15 +83,7 @@ public string ClassName { get { - StringBuilder windowClassName = new StringBuilder(300); - var numCharactersWritten = NativeMethods.GetClassName(Hwnd, windowClassName, windowClassName.MaxCapacity); - - if (numCharactersWritten == 0) - { - return string.Empty; - } - - return windowClassName.ToString(); + return GetWindowClassName(Hwnd); } } @@ -236,6 +177,7 @@ public Window(IntPtr hwnd) { // TODO: Add verification as to whether the window handle is valid this.hwnd = hwnd; + processInfo = CreateWindowProcessInstance(hwnd); } /// @@ -248,7 +190,7 @@ public void SwitchToWindow() // to use ShowWindow for switching tabs in IE // 2) SetForegroundWindow fails on minimized windows // Using Ordinal since this is internal - if (ProcessName.ToUpperInvariant().Equals("IEXPLORE.EXE", StringComparison.Ordinal) || !Minimized) + if (processInfo.Name.ToUpperInvariant().Equals("IEXPLORE.EXE", StringComparison.Ordinal) || !Minimized) { NativeMethods.SetForegroundWindow(Hwnd); } @@ -271,7 +213,7 @@ public void SwitchToWindow() public override string ToString() { // Using CurrentCulture since this is user facing - return Title + " (" + ProcessName.ToUpper(CultureInfo.CurrentCulture) + ")"; + return Title + " (" + processInfo.Name.ToUpper(CultureInfo.CurrentCulture) + ")"; } /// @@ -309,36 +251,120 @@ public enum WindowSizeState } /// - /// Gets the name of the process using the window handle + /// Returns if the window has cloak state in DWM /// - /// The handle to the window - /// A string representing the process name or an empty string if the function fails - private string GetProcessNameFromWindowHandle(IntPtr hwnd) + /// The state (none, app, ...) of the window + public WindowCloakState GetWindowCloakState() { - uint processId = GetProcessIDFromWindowHandle(hwnd); - ProcessID = processId; - IntPtr processHandle = NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.QueryLimitedInformation, true, (int)processId); - StringBuilder processName = new StringBuilder(MaximumFileNameLength); + _ = NativeMethods.DwmGetWindowAttribute(Hwnd, (int)NativeMethods.DwmWindowAttribute.Cloaked, out int isCloakedState, NativeMethods.GetSizeOfUInt()); - if (NativeMethods.GetProcessImageFileName(processHandle, processName, MaximumFileNameLength) != 0) + switch (isCloakedState) { - return processName.ToString().Split('\\').Reverse().ToArray()[0]; + case (int)NativeMethods.DwmWindowCloakState.None: + return WindowCloakState.None; + case (int)NativeMethods.DwmWindowCloakState.CloakedApp: + return WindowCloakState.App; + case (int)NativeMethods.DwmWindowCloakState.CloakedShell: + return WindowCloakState.Shell; + case (int)NativeMethods.DwmWindowCloakState.CloakedInherited: + return WindowCloakState.Inherited; + default: + return WindowCloakState.Unknown; } - else + } + + /// + /// Enum to simplify the cloak state of the window + /// + public enum WindowCloakState + { + None, + App, + Shell, + Inherited, + Unknown, + } + + /// + /// Returns the class name of a window. + /// + /// Handle to the window. + /// Class name + private static string GetWindowClassName(IntPtr hwnd) + { + StringBuilder windowClassName = new StringBuilder(300); + var numCharactersWritten = NativeMethods.GetClassName(hwnd, windowClassName, windowClassName.MaxCapacity); + + if (numCharactersWritten == 0) { return string.Empty; } + + return windowClassName.ToString(); } /// - /// Gets the process ID for the Window handle + /// Gets an instance of form process cache or creates a new one. A new one will be added to the cache. /// - /// The handle to the window - /// The process ID - private static uint GetProcessIDFromWindowHandle(IntPtr hwnd) + /// The handle to the window + /// A new Instance of type + private static WindowProcess CreateWindowProcessInstance(IntPtr hWindow) { - _ = NativeMethods.GetWindowThreadProcessId(hwnd, out uint processId); - return processId; + lock (_handlesToProcessCache) + { + if (_handlesToProcessCache.Count > 7000) + { + Debug.Print("Clearing Process Cache because it's size is " + _handlesToProcessCache.Count); + _handlesToProcessCache.Clear(); + } + + // Add window's process to cache if missing + if (!_handlesToProcessCache.ContainsKey(hWindow)) + { + // Get process ID and name + var processId = WindowProcess.GetProcessIDFromWindowHandle(hWindow); + var threadId = WindowProcess.GetThreadIDFromWindowHandle(hWindow); + var processName = WindowProcess.GetProcessNameFromProcessID(processId).ToString().Split('\\').Reverse().ToArray()[0]; + + if (processName.Length != 0) + { + _handlesToProcessCache.Add(hWindow, new WindowProcess(processId, threadId, processName)); + } + else + { + Wox.Plugin.Logger.Log.Error($"Invalid process {processId} ({processName}) for window handle {hWindow}.", typeof(Window)); + _handlesToProcessCache.Add(hWindow, new WindowProcess(0, 0, string.Empty)); + } + } + + // Correct the process data if the window belongs to a packaged app hosted by 'ApplicationFrameHost.exe' + if (_handlesToProcessCache[hWindow].Name.ToUpperInvariant() == "APPLICATIONFRAMEHOST.EXE") + { + new Task(() => + { + NativeMethods.CallBackPtr callbackptr = new NativeMethods.CallBackPtr((IntPtr hwnd, IntPtr lParam) => + { + if (GetWindowClassName(hwnd) == "Windows.UI.Core.CoreWindow") + { + var childProcessId = WindowProcess.GetProcessIDFromWindowHandle(hwnd); + var childThreadId = WindowProcess.GetThreadIDFromWindowHandle(hwnd); + var childProcessName = WindowProcess.GetProcessNameFromProcessID(childProcessId); + + // Update process info in cache + _handlesToProcessCache[hWindow].UpdateProcessInfo(childProcessId, childThreadId, childProcessName); + return false; + } + else + { + return true; + } + }); + _ = NativeMethods.EnumChildWindows(hWindow, callbackptr, 0); + }).Start(); + } + + return _handlesToProcessCache[hWindow]; + } } } } diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs new file mode 100644 index 000000000000..8b280e9bbe1e --- /dev/null +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs @@ -0,0 +1,183 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/ +using System; +using System.Linq; +using System.Text; + +namespace Microsoft.Plugin.WindowWalker.Components +{ + /// + /// Represents the process data of an open window. This class is used in the process cache and for the process object of the open window + /// + public class WindowProcess + { + /// + /// Maximum size of a file name + /// + private const int MaximumFileNameLength = 1000; + + /// + /// An indicator if the window belongs to an 'Universal Windows Platform (UWP)' process + /// + private readonly bool _isUwpApp; + + /// + /// The process Id of the window process + /// + private uint processID; + + /// + /// The thread Id of the window within the process object + /// + private uint threadID; + + /// + /// The process file name of the window process + /// + private string processName; + + /// + /// An indicator if the process of the window is running elevated + /// + private bool isElevated; + + /// + /// Gets the id of the process + /// + public uint ProcessID + { + get { return processID; } + } + + /// + /// Gets the id of the thread + /// + public uint ThreadID + { + get { return threadID; } + } + + /// + /// Gets the name of the process + /// + public string Name + { + get { return processName; } + } + + /// + /// Gets a value indicating whether the process runs elevated or not + /// + public bool IsRunningElevated + { + get { return isElevated; } + } + + /// + /// Gets a value indicating whether the window belongs to an 'Universal Windows Platform (UWP)' process + /// + public bool IsUwpApp + { + get { return _isUwpApp; } + } + + /// + /// Initializes a new instance of the class. + /// + /// New process id. + /// New thread id. + /// New process name. + public WindowProcess(uint pid, uint tid, string name) + { + // TODO: Add verification as to wether the process id and thread id is valid + processID = pid; + threadID = tid; + processName = name; + _isUwpApp = processName.ToUpperInvariant().Equals("APPLICATIONFRAMEHOST.EXE", StringComparison.Ordinal); + + // Process can be elevated only if process id is not 0. (Dummy value on error.) Please have in mind here that pid=0 is the idle process. + isElevated = (pid != 0) ? GetProcessElevationStateFromProcessID(pid) : false; + } + + /// + /// Updates the process information of the instance. + /// + /// New process id. + /// New thread id. + /// New process name. + public void UpdateProcessInfo(uint pid, uint tid, string name) + { + processID = pid; + threadID = tid; + processName = name; + + // Process can be elevated only if process id is not 0 (Dummy value on error) + isElevated = (pid != 0) ? GetProcessElevationStateFromProcessID(pid) : false; + } + + /// + /// Gets the process ID for the window handle + /// + /// The handle to the window + /// The process ID + public static uint GetProcessIDFromWindowHandle(IntPtr hwnd) + { + _ = NativeMethods.GetWindowThreadProcessId(hwnd, out uint processId); + return processId; + } + + /// + /// Gets the thread ID for the window handle + /// + /// The handle to the window + /// The thread ID + public static uint GetThreadIDFromWindowHandle(IntPtr hwnd) + { + var threadId = NativeMethods.GetWindowThreadProcessId(hwnd, out _); + return threadId; + } + + /// + /// Gets the process name for the process ID + /// + /// The id of the process/param> + /// A string representing the process name or an empty string if the function fails + public static string GetProcessNameFromProcessID(uint pid) + { + IntPtr processHandle = NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.QueryLimitedInformation, true, (int)pid); + StringBuilder processName = new StringBuilder(MaximumFileNameLength); + + if (NativeMethods.GetProcessImageFileName(processHandle, processName, MaximumFileNameLength) != 0) + { + return processName.ToString().Split('\\').Reverse().ToArray()[0]; + } + else + { + return string.Empty; + } + } + + /// + /// Gets a boolean value indicating whether a process runs elevated. (Note: This only works if PowerToys Run doesn't run elevated.) + /// + /// The process ID of the process + /// True if elevated and false if not. + private static bool GetProcessElevationStateFromProcessID(uint pid) + { + _ = NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.AllAccess, true, (int)pid); + + if (NativeMethods.GetLastWin32Error() == 5) + { + // Error 5 = ERROR_ACCESS_DENIED + return true; + } + else + { + return false; + } + } + } +} diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs index 3463fafdda37..1f8e5df0e92c 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs @@ -43,12 +43,13 @@ public List Query(Query query) { Title = x.Result.Title, IcoPath = IconPath, - SubTitle = Properties.Resources.wox_plugin_windowwalker_running + ": " + x.Result.ProcessName, + SubTitle = Properties.Resources.wox_plugin_windowwalker_running + ": " + x.Result.ProcessInfo.Name, Action = c => { x.Result.SwitchToWindow(); return true; }, + ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nIs running elevated: {x.Result.ProcessInfo.IsRunningElevated}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), }).ToList(); } From 6c37d135892bd9ab401f70738a901e76ece6d94e Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 11 Jan 2022 14:01:50 +0100 Subject: [PATCH 02/32] Improvements --- .../Components/NativeMethods.cs | 9 ++++---- .../Components/Window.cs | 23 +++++++++++++++---- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs index 31d04a44b0a6..7ec63808aaca 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs @@ -914,14 +914,13 @@ public enum ExtendedWindowStyles : uint [DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int msg, int wParam); + /// + /// Returns the last Win32 Error code thrown by a native method if enabled for this method. + /// + /// The error code as int value. public static int GetLastWin32Error() { return Marshal.GetLastWin32Error(); } - - public static int GetSizeOfUInt() - { - return Marshal.SizeOf(typeof(uint)); - } } } diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs index a8e25f19b946..2c2f92d85862 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs @@ -98,6 +98,18 @@ public bool Visible } } + /// + /// Gets a value indicating whether the window is cloaked (true) or not (false). + /// (A cloaked window is not visible to the user. But the window is still composed by DWM.) + /// + public bool IsCloaked + { + get + { + return GetWindowCloakState() != WindowCloakState.None; + } + } + /// /// Gets a value indicating whether determines whether the specified window handle identifies an existing window. /// @@ -251,12 +263,13 @@ public enum WindowSizeState } /// - /// Returns if the window has cloak state in DWM + /// Returns the window cloak state from DWM + /// (A cloaked window is not visible to the user. But the window is still composed by DWM.) /// /// The state (none, app, ...) of the window public WindowCloakState GetWindowCloakState() { - _ = NativeMethods.DwmGetWindowAttribute(Hwnd, (int)NativeMethods.DwmWindowAttribute.Cloaked, out int isCloakedState, NativeMethods.GetSizeOfUInt()); + _ = NativeMethods.DwmGetWindowAttribute(Hwnd, (int)NativeMethods.DwmWindowAttribute.Cloaked, out int isCloakedState, sizeof(uint)); switch (isCloakedState) { @@ -324,7 +337,7 @@ private static WindowProcess CreateWindowProcessInstance(IntPtr hWindow) // Get process ID and name var processId = WindowProcess.GetProcessIDFromWindowHandle(hWindow); var threadId = WindowProcess.GetThreadIDFromWindowHandle(hWindow); - var processName = WindowProcess.GetProcessNameFromProcessID(processId).ToString().Split('\\').Reverse().ToArray()[0]; + var processName = WindowProcess.GetProcessNameFromProcessID(processId); if (processName.Length != 0) { @@ -337,13 +350,15 @@ private static WindowProcess CreateWindowProcessInstance(IntPtr hWindow) } } - // Correct the process data if the window belongs to a packaged app hosted by 'ApplicationFrameHost.exe' + // Correct the process data if the window belongs to a uwp app hosted by 'ApplicationFrameHost.exe' if (_handlesToProcessCache[hWindow].Name.ToUpperInvariant() == "APPLICATIONFRAMEHOST.EXE") { new Task(() => { NativeMethods.CallBackPtr callbackptr = new NativeMethods.CallBackPtr((IntPtr hwnd, IntPtr lParam) => { + // Every uwp app main window has at leaszt three childs. Only the one we are interested in has the class "Windows.UI.Core.CoreWindow" and is assigned to the real app process. + // (The other ones have a class name that begins with the string "ApplicationFrame".) if (GetWindowClassName(hwnd) == "Windows.UI.Core.CoreWindow") { var childProcessId = WindowProcess.GetProcessIDFromWindowHandle(hwnd); From e29cc820f6550a25c6ced573e07084990a9b3236 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 11 Jan 2022 14:26:12 +0100 Subject: [PATCH 03/32] hide uwp non-windows (#13637) --- .../Components/OpenWindows.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs index 81ead455a9cf..a9e5368090ab 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs @@ -95,7 +95,12 @@ public bool WindowEnumerationCallBack(IntPtr hwnd, IntPtr lParam) (!newWindow.IsToolWindow || newWindow.IsAppWindow) && !newWindow.TaskListDeleted && newWindow.ClassName != "Windows.UI.Core.CoreWindow" && newWindow.ProcessInfo.Name != _powerLauncherExe) { - windows.Add(newWindow); + // To hide (not add) preloaded uwp app windows that are invisble to the user we check thet cloak state in DWM to be "none". (Issue #13637.) + // (If user asking to see these windows agin we can add an optional plugin setting in the future.) + if (!newWindow.IsCloaked) + { + windows.Add(newWindow); + } } return true; From fd2a719adeb1ee926bdbe46ec773232440fa20b3 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 11 Jan 2022 14:27:02 +0100 Subject: [PATCH 04/32] update debug tool tip --- .../launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs index 1f8e5df0e92c..f9b034f2f0a6 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs @@ -49,7 +49,7 @@ public List Query(Query query) x.Result.SwitchToWindow(); return true; }, - ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nIs running elevated: {x.Result.ProcessInfo.IsRunningElevated}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), + ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nIs running elevated: {x.Result.ProcessInfo.IsRunningElevated}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nIs window cloaked: {x.Result.IsCloaked}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), }).ToList(); } From 5d58d3276c43ea7e667802cf6e03fc168b256633 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 11 Jan 2022 14:45:11 +0100 Subject: [PATCH 05/32] fix spelling and comments --- .github/actions/spell-check/expect.txt | 1 + .../Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs | 2 +- .../Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs | 4 ++-- .../Microsoft.Plugin.WindowWalker/Components/Window.cs | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 8104477280e4..378c36d11f85 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -721,6 +721,7 @@ HOLDESC homepage homljgmgpmcbpjbnjpfijnhipfkiclkd HOOKPROC +Hostbackdropbrush hostname hotkeycontrol hotkeys diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs index 7ec63808aaca..54177a031cba 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs @@ -276,7 +276,7 @@ public enum DwmWindowAttribute BorderColor, CaptionColor, TextColor, - VisibelFrameBorderTickness, + VisibleFrameBorderThickness, Last, } diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs index a9e5368090ab..9faeb42f4a01 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs @@ -95,8 +95,8 @@ public bool WindowEnumerationCallBack(IntPtr hwnd, IntPtr lParam) (!newWindow.IsToolWindow || newWindow.IsAppWindow) && !newWindow.TaskListDeleted && newWindow.ClassName != "Windows.UI.Core.CoreWindow" && newWindow.ProcessInfo.Name != _powerLauncherExe) { - // To hide (not add) preloaded uwp app windows that are invisble to the user we check thet cloak state in DWM to be "none". (Issue #13637.) - // (If user asking to see these windows agin we can add an optional plugin setting in the future.) + // To hide (not add) preloaded uwp app windows that are invisible to the user we check the cloak state in DWM to be "none". (Issue #13637.) + // (If user asking to see these windows again we can add an optional plugin setting in the future.) if (!newWindow.IsCloaked) { windows.Add(newWindow); diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs index 2c2f92d85862..be5e16b6e36d 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs @@ -351,13 +351,14 @@ private static WindowProcess CreateWindowProcessInstance(IntPtr hWindow) } // Correct the process data if the window belongs to a uwp app hosted by 'ApplicationFrameHost.exe' + // (This only works if the window isn't minimized. For minimized windows the required child window isn't assigned.) if (_handlesToProcessCache[hWindow].Name.ToUpperInvariant() == "APPLICATIONFRAMEHOST.EXE") { new Task(() => { NativeMethods.CallBackPtr callbackptr = new NativeMethods.CallBackPtr((IntPtr hwnd, IntPtr lParam) => { - // Every uwp app main window has at leaszt three childs. Only the one we are interested in has the class "Windows.UI.Core.CoreWindow" and is assigned to the real app process. + // Every uwp app main window has at least three child windows. Only the one we are interested in has the class "Windows.UI.Core.CoreWindow" and is assigned to the real app process. // (The other ones have a class name that begins with the string "ApplicationFrame".) if (GetWindowClassName(hwnd) == "Windows.UI.Core.CoreWindow") { From 552fefce12476f35b0e4539dde5a9c3a5e03b0fb Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 11 Jan 2022 14:51:59 +0100 Subject: [PATCH 06/32] disable tool tip --- .../launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs index f9b034f2f0a6..bcaafe10c77b 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs @@ -49,7 +49,9 @@ public List Query(Query query) x.Result.SwitchToWindow(); return true; }, - ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nIs running elevated: {x.Result.ProcessInfo.IsRunningElevated}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nIs window cloaked: {x.Result.IsCloaked}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), + + // For debugging you can remove the comment sign in the next line. + // ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nIs running elevated: {x.Result.ProcessInfo.IsRunningElevated}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nIs window cloaked: {x.Result.IsCloaked}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), }).ToList(); } From eb00d6d5855a53bc0b4bf2148312a8d20dd4c206 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 11 Jan 2022 15:08:34 +0100 Subject: [PATCH 07/32] fix doc links --- .../modules/launcher/plugins/windowwalker.md | 14 +++++++------- .../launcher/plugins/windowwalker.md.bak | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 doc/devdocs/modules/launcher/plugins/windowwalker.md.bak diff --git a/doc/devdocs/modules/launcher/plugins/windowwalker.md b/doc/devdocs/modules/launcher/plugins/windowwalker.md index 401cfa307a9e..fed601e767c9 100644 --- a/doc/devdocs/modules/launcher/plugins/windowwalker.md +++ b/doc/devdocs/modules/launcher/plugins/windowwalker.md @@ -3,16 +3,16 @@ The window walker plugin matches the user entered query with the open windows on ![Image of Window Walker plugin](/doc/images/launcher/plugins/windowwalker.png) -### [`OpenWindows.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs) -- The window walker plugin uses the `EnumWindows` function to enumerate all the open windows in the [`OpenWindows.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs) class. +### [`OpenWindows.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs) +- The window walker plugin uses the `EnumWindows` function to enumerate all the open windows in the [`OpenWindows.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs) class. -### [`SearchController.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) -- The [`SearchController`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) encapsulates the functions needed to search and find matches. +### [`SearchController.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) +- The [`SearchController`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) encapsulates the functions needed to search and find matches. - It is responsible for updating the search text and performing a fuzzy search on all the open windows in an asynchronous manner. -### [`Window.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) -- The [`Window`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) class represents a specific window and has functions to get the name of the process, the state of the window (whether it is visible or not), and the `SwitchTowindow` function which switches the desktop focus to the selected window. This action is performed when the user clicks on a window walker plugin result. +### [`Window.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) +- The [`Window`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) class represents a specific window and has functions to get the name of the process, the state of the window (whether it is visible or not), and the `SwitchTowindow` function which switches the desktop focus to the selected window. This action is performed when the user clicks on a window walker plugin result. ### Score -The window walker plugin uses [`FuzzyMatching`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/FuzzyMatching.cs) to get the matching indices and calculates the score by creating a 2 dimensional array of the window and the query text. +The window walker plugin uses [`FuzzyMatching`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/FuzzyMatching.cs) to get the matching indices and calculates the score by creating a 2 dimensional array of the window and the query text. diff --git a/doc/devdocs/modules/launcher/plugins/windowwalker.md.bak b/doc/devdocs/modules/launcher/plugins/windowwalker.md.bak new file mode 100644 index 000000000000..401cfa307a9e --- /dev/null +++ b/doc/devdocs/modules/launcher/plugins/windowwalker.md.bak @@ -0,0 +1,18 @@ +# Window Walker plugin +The window walker plugin matches the user entered query with the open windows on the system. + +![Image of Window Walker plugin](/doc/images/launcher/plugins/windowwalker.png) + +### [`OpenWindows.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs) +- The window walker plugin uses the `EnumWindows` function to enumerate all the open windows in the [`OpenWindows.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs) class. + + +### [`SearchController.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) +- The [`SearchController`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) encapsulates the functions needed to search and find matches. +- It is responsible for updating the search text and performing a fuzzy search on all the open windows in an asynchronous manner. + +### [`Window.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) +- The [`Window`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) class represents a specific window and has functions to get the name of the process, the state of the window (whether it is visible or not), and the `SwitchTowindow` function which switches the desktop focus to the selected window. This action is performed when the user clicks on a window walker plugin result. + +### Score +The window walker plugin uses [`FuzzyMatching`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/FuzzyMatching.cs) to get the matching indices and calculates the score by creating a 2 dimensional array of the window and the query text. From 49df906532f340614e8d2a437c51751d607104b4 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 11 Jan 2022 15:08:56 +0100 Subject: [PATCH 08/32] remove obsolete using --- .../Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs index be5e16b6e36d..dd426e95af6a 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; -using System.Linq; using System.Text; using System.Threading.Tasks; From 6264e115d244e612130ab822dfd29dcb6c601cdb Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 11 Jan 2022 15:32:59 +0100 Subject: [PATCH 09/32] Update docs --- .../modules/launcher/plugins/windowwalker.md | 7 +++++-- .../launcher/plugins/windowwalker.md.bak | 18 ------------------ .../Components/Window.cs | 4 ++-- 3 files changed, 7 insertions(+), 22 deletions(-) delete mode 100644 doc/devdocs/modules/launcher/plugins/windowwalker.md.bak diff --git a/doc/devdocs/modules/launcher/plugins/windowwalker.md b/doc/devdocs/modules/launcher/plugins/windowwalker.md index fed601e767c9..3a21077258d7 100644 --- a/doc/devdocs/modules/launcher/plugins/windowwalker.md +++ b/doc/devdocs/modules/launcher/plugins/windowwalker.md @@ -6,13 +6,16 @@ The window walker plugin matches the user entered query with the open windows on ### [`OpenWindows.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs) - The window walker plugin uses the `EnumWindows` function to enumerate all the open windows in the [`OpenWindows.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs) class. - ### [`SearchController.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) - The [`SearchController`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) encapsulates the functions needed to search and find matches. - It is responsible for updating the search text and performing a fuzzy search on all the open windows in an asynchronous manner. ### [`Window.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) -- The [`Window`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) class represents a specific window and has functions to get the name of the process, the state of the window (whether it is visible or not), and the `SwitchTowindow` function which switches the desktop focus to the selected window. This action is performed when the user clicks on a window walker plugin result. +- The [`Window`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) class represents a specific window and has functions to get the name of the window, the state of the window (whether it is visible or not), and the `SwitchTowindow` function which switches the desktop focus to the selected window. This action is performed when the user clicks on a window walker plugin result. +- The `Window` class holds a static cache with the process information of all windows we know so far and each window instance has a property which holds its process information (name, file, ...). The process data in the cache and the window property are of the type `WindowProcess`. + +### [`WindowProcess.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs) +- The [`WindowProcess`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs) class represents a specific process for a window. It contains static methods to query process information from the system. And it contains instantiable methods and properties to hold/retrieve the process information we want to know about a window's process. ### Score The window walker plugin uses [`FuzzyMatching`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/FuzzyMatching.cs) to get the matching indices and calculates the score by creating a 2 dimensional array of the window and the query text. diff --git a/doc/devdocs/modules/launcher/plugins/windowwalker.md.bak b/doc/devdocs/modules/launcher/plugins/windowwalker.md.bak deleted file mode 100644 index 401cfa307a9e..000000000000 --- a/doc/devdocs/modules/launcher/plugins/windowwalker.md.bak +++ /dev/null @@ -1,18 +0,0 @@ -# Window Walker plugin -The window walker plugin matches the user entered query with the open windows on the system. - -![Image of Window Walker plugin](/doc/images/launcher/plugins/windowwalker.png) - -### [`OpenWindows.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs) -- The window walker plugin uses the `EnumWindows` function to enumerate all the open windows in the [`OpenWindows.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs) class. - - -### [`SearchController.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) -- The [`SearchController`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) encapsulates the functions needed to search and find matches. -- It is responsible for updating the search text and performing a fuzzy search on all the open windows in an asynchronous manner. - -### [`Window.cs`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) -- The [`Window`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) class represents a specific window and has functions to get the name of the process, the state of the window (whether it is visible or not), and the `SwitchTowindow` function which switches the desktop focus to the selected window. This action is performed when the user clicks on a window walker plugin result. - -### Score -The window walker plugin uses [`FuzzyMatching`](src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/FuzzyMatching.cs) to get the matching indices and calculates the score by creating a 2 dimensional array of the window and the query text. diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs index dd426e95af6a..75eeedd3bd87 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs @@ -23,8 +23,8 @@ public class Window private readonly IntPtr hwnd; /// - /// The list of owners of a window so that we don't have to - /// constantly query for the process owning a specific window + /// A static cache for the process data of all known windows + /// that we don't have to query the data every time /// private static readonly Dictionary _handlesToProcessCache = new Dictionary(); From 6f1e89f1d5037b2a5658eba765a7fe8a0bccdcb0 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Tue, 11 Jan 2022 15:36:18 +0100 Subject: [PATCH 10/32] fix spelling --- doc/devdocs/modules/launcher/plugins/windowwalker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/devdocs/modules/launcher/plugins/windowwalker.md b/doc/devdocs/modules/launcher/plugins/windowwalker.md index 3a21077258d7..9327e362a127 100644 --- a/doc/devdocs/modules/launcher/plugins/windowwalker.md +++ b/doc/devdocs/modules/launcher/plugins/windowwalker.md @@ -15,7 +15,7 @@ The window walker plugin matches the user entered query with the open windows on - The `Window` class holds a static cache with the process information of all windows we know so far and each window instance has a property which holds its process information (name, file, ...). The process data in the cache and the window property are of the type `WindowProcess`. ### [`WindowProcess.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs) -- The [`WindowProcess`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs) class represents a specific process for a window. It contains static methods to query process information from the system. And it contains instantiable methods and properties to hold/retrieve the process information we want to know about a window's process. +- The [`WindowProcess`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs) class represents a specific process for a window. It contains static methods to query process information from the system. And it contains instance methods and properties to hold/retrieve the process information we want to know about a window's process. ### Score The window walker plugin uses [`FuzzyMatching`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/FuzzyMatching.cs) to get the matching indices and calculates the score by creating a 2 dimensional array of the window and the query text. From 072fe14611d72b747c52c0ad9938a9fee31a0548 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Thu, 13 Jan 2022 15:04:14 +0100 Subject: [PATCH 11/32] rename elevation property and test method --- .../Components/WindowProcess.cs | 20 +++++++++---------- .../Microsoft.Plugin.WindowWalker/Main.cs | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs index 8b280e9bbe1e..aa012de09b3a 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs @@ -40,9 +40,9 @@ public class WindowProcess private string processName; /// - /// An indicator if the process of the window is running elevated + /// An indicator whether full access to the process is denied or not /// - private bool isElevated; + private bool fullAccessDenied; /// /// Gets the id of the process @@ -69,11 +69,11 @@ public string Name } /// - /// Gets a value indicating whether the process runs elevated or not + /// Gets a value indicating whether full access to the process is denied or not /// - public bool IsRunningElevated + public bool IsFullAccessDenied { - get { return isElevated; } + get { return fullAccessDenied; } } /// @@ -99,7 +99,7 @@ public WindowProcess(uint pid, uint tid, string name) _isUwpApp = processName.ToUpperInvariant().Equals("APPLICATIONFRAMEHOST.EXE", StringComparison.Ordinal); // Process can be elevated only if process id is not 0. (Dummy value on error.) Please have in mind here that pid=0 is the idle process. - isElevated = (pid != 0) ? GetProcessElevationStateFromProcessID(pid) : false; + fullAccessDenied = (pid != 0) ? TestProcessAccessUsingAllAccessFlag(pid) : false; } /// @@ -115,7 +115,7 @@ public void UpdateProcessInfo(uint pid, uint tid, string name) processName = name; // Process can be elevated only if process id is not 0 (Dummy value on error) - isElevated = (pid != 0) ? GetProcessElevationStateFromProcessID(pid) : false; + fullAccessDenied = (pid != 0) ? TestProcessAccessUsingAllAccessFlag(pid) : false; } /// @@ -161,11 +161,11 @@ public static string GetProcessNameFromProcessID(uint pid) } /// - /// Gets a boolean value indicating whether a process runs elevated. (Note: This only works if PowerToys Run doesn't run elevated.) + /// Gets a boolean value indicating whether the access to a process using the AllAccess flag is denied or not. /// /// The process ID of the process - /// True if elevated and false if not. - private static bool GetProcessElevationStateFromProcessID(uint pid) + /// True if denied and false if not. + private static bool TestProcessAccessUsingAllAccessFlag(uint pid) { _ = NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.AllAccess, true, (int)pid); diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs index bcaafe10c77b..08eaa4c60c2f 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs @@ -51,7 +51,7 @@ public List Query(Query query) }, // For debugging you can remove the comment sign in the next line. - // ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nIs running elevated: {x.Result.ProcessInfo.IsRunningElevated}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nIs window cloaked: {x.Result.IsCloaked}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), + ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nIs full access denied: {x.Result.ProcessInfo.IsFullAccessDenied}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nIs window cloaked: {x.Result.IsCloaked}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), }).ToList(); } From a53d0c9df13bdbdf75bb675438d21c16fe1322cd Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Thu, 13 Jan 2022 15:41:09 +0100 Subject: [PATCH 12/32] Add property to WindowProcess class --- .../Components/WindowProcess.cs | 24 +++++++++++++++++++ .../Microsoft.Plugin.WindowWalker/Main.cs | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs index aa012de09b3a..9e0f72b0ecc1 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs @@ -4,6 +4,7 @@ // Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/ using System; +using System.Diagnostics; using System.Linq; using System.Text; @@ -160,6 +161,29 @@ public static string GetProcessNameFromProcessID(uint pid) } } + public bool DoesExist + { + get + { + try + { + var p = Process.GetProcessById((int)processID); + p.Dispose(); + return true; + } + catch (InvalidOperationException) + { + // Thrown when process not exist. + return false; + } + catch (ArgumentException) + { + // Thrown when process not exist. + return false; + } + } + } + /// /// Gets a boolean value indicating whether the access to a process using the AllAccess flag is denied or not. /// diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs index 08eaa4c60c2f..1d842f1c6074 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs @@ -51,7 +51,7 @@ public List Query(Query query) }, // For debugging you can remove the comment sign in the next line. - ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nIs full access denied: {x.Result.ProcessInfo.IsFullAccessDenied}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nIs window cloaked: {x.Result.IsCloaked}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), + ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nProcess exists: {x.Result.ProcessInfo.DoesExist}\nIs full access denied: {x.Result.ProcessInfo.IsFullAccessDenied}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nIs window cloaked: {x.Result.IsCloaked}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), }).ToList(); } From 18d45a3ae403df280782baba7432e72f773600b8 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Thu, 13 Jan 2022 16:43:18 +0100 Subject: [PATCH 13/32] Close process handles correctly if not used anymore --- .../Components/NativeMethods.cs | 20 +++++++++++++++++++ .../Components/WindowProcess.cs | 6 +++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs index 54177a031cba..a4b5892502cd 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs @@ -914,6 +914,10 @@ public enum ExtendedWindowStyles : uint [DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int msg, int wParam); + [DllImport("kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CloseHandle(IntPtr hObject); + /// /// Returns the last Win32 Error code thrown by a native method if enabled for this method. /// @@ -922,5 +926,21 @@ public static int GetLastWin32Error() { return Marshal.GetLastWin32Error(); } + + /// + /// Closes a process handle if it is not null. + /// + /// Process handle to close. + /// Zero if native method fails and nonzero if the native method succeeds. + public static bool CloseProcessHandle(IntPtr pHandle) + { + if (pHandle == null) + { + // Return true if nothing to close. + return true; + } + + return CloseHandle(pHandle); + } } } diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs index 9e0f72b0ecc1..59bc3a0900a0 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs @@ -153,10 +153,12 @@ public static string GetProcessNameFromProcessID(uint pid) if (NativeMethods.GetProcessImageFileName(processHandle, processName, MaximumFileNameLength) != 0) { + NativeMethods.CloseProcessHandle(processHandle); return processName.ToString().Split('\\').Reverse().ToArray()[0]; } else { + NativeMethods.CloseProcessHandle(processHandle); return string.Empty; } } @@ -191,15 +193,17 @@ public bool DoesExist /// True if denied and false if not. private static bool TestProcessAccessUsingAllAccessFlag(uint pid) { - _ = NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.AllAccess, true, (int)pid); + var processHandle = NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.AllAccess, true, (int)pid); if (NativeMethods.GetLastWin32Error() == 5) { // Error 5 = ERROR_ACCESS_DENIED + NativeMethods.CloseProcessHandle(processHandle); return true; } else { + NativeMethods.CloseProcessHandle(processHandle); return false; } } From f180dc80333d8f2a891fe292f220d699581dd2a4 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Thu, 13 Jan 2022 17:10:50 +0100 Subject: [PATCH 14/32] cleanup coed --- .../Components/Window.cs | 2 +- .../Components/WindowProcess.cs | 63 +++++-------------- 2 files changed, 15 insertions(+), 50 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs index 75eeedd3bd87..694861713387 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs @@ -366,7 +366,7 @@ private static WindowProcess CreateWindowProcessInstance(IntPtr hWindow) var childProcessName = WindowProcess.GetProcessNameFromProcessID(childProcessId); // Update process info in cache - _handlesToProcessCache[hWindow].UpdateProcessInfo(childProcessId, childThreadId, childProcessName); + _handlesToProcessCache[hWindow] = new WindowProcess(childProcessId, childThreadId, childProcessName); return false; } else diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs index 59bc3a0900a0..342984a8b215 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - -// Code forked from Betsegaw Tadele's https://github.com/betsegaw/windowwalker/ using System; using System.Diagnostics; using System.Linq; @@ -25,32 +23,12 @@ public class WindowProcess /// private readonly bool _isUwpApp; - /// - /// The process Id of the window process - /// - private uint processID; - - /// - /// The thread Id of the window within the process object - /// - private uint threadID; - - /// - /// The process file name of the window process - /// - private string processName; - - /// - /// An indicator whether full access to the process is denied or not - /// - private bool fullAccessDenied; - /// /// Gets the id of the process /// public uint ProcessID { - get { return processID; } + get; private set; } /// @@ -58,7 +36,7 @@ public uint ProcessID /// public uint ThreadID { - get { return threadID; } + get; private set; } /// @@ -66,7 +44,7 @@ public uint ThreadID /// public string Name { - get { return processName; } + get; private set; } /// @@ -74,7 +52,7 @@ public string Name /// public bool IsFullAccessDenied { - get { return fullAccessDenied; } + get; private set; } /// @@ -88,35 +66,19 @@ public bool IsUwpApp /// /// Initializes a new instance of the class. /// - /// New process id. + /// New process id. /// New thread id. /// New process name. public WindowProcess(uint pid, uint tid, string name) { // TODO: Add verification as to wether the process id and thread id is valid - processID = pid; - threadID = tid; - processName = name; - _isUwpApp = processName.ToUpperInvariant().Equals("APPLICATIONFRAMEHOST.EXE", StringComparison.Ordinal); - - // Process can be elevated only if process id is not 0. (Dummy value on error.) Please have in mind here that pid=0 is the idle process. - fullAccessDenied = (pid != 0) ? TestProcessAccessUsingAllAccessFlag(pid) : false; - } - - /// - /// Updates the process information of the instance. - /// - /// New process id. - /// New thread id. - /// New process name. - public void UpdateProcessInfo(uint pid, uint tid, string name) - { - processID = pid; - threadID = tid; - processName = name; + ProcessID = pid; + ThreadID = tid; + Name = name; + _isUwpApp = Name.ToUpperInvariant().Equals("APPLICATIONFRAMEHOST.EXE", StringComparison.Ordinal); // Process can be elevated only if process id is not 0 (Dummy value on error) - fullAccessDenied = (pid != 0) ? TestProcessAccessUsingAllAccessFlag(pid) : false; + IsFullAccessDenied = (pid != 0) ? TestProcessAccessUsingAllAccessFlag(pid) : false; } /// @@ -163,13 +125,16 @@ public static string GetProcessNameFromProcessID(uint pid) } } + /// + /// Gets a value indicating whether the proces exists on the machine + /// public bool DoesExist { get { try { - var p = Process.GetProcessById((int)processID); + var p = Process.GetProcessById((int)ProcessID); p.Dispose(); return true; } From e4aea0d680fadbebaa4883e784e936f0eb12d192 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Thu, 13 Jan 2022 17:31:32 +0100 Subject: [PATCH 15/32] fix bug with sticky notes process --- .../Microsoft.Plugin.WindowWalker/Components/Window.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs index 694861713387..182665a13768 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs @@ -357,9 +357,9 @@ private static WindowProcess CreateWindowProcessInstance(IntPtr hWindow) { NativeMethods.CallBackPtr callbackptr = new NativeMethods.CallBackPtr((IntPtr hwnd, IntPtr lParam) => { - // Every uwp app main window has at least three child windows. Only the one we are interested in has the class "Windows.UI.Core.CoreWindow" and is assigned to the real app process. + // Every uwp app main window has at least three child windows. Only the one we are interested in has a class starting with "Windows.UI.Core." and is assigned to the real app process. // (The other ones have a class name that begins with the string "ApplicationFrame".) - if (GetWindowClassName(hwnd) == "Windows.UI.Core.CoreWindow") + if (GetWindowClassName(hwnd).StartsWith("Windows.UI.Core.", StringComparison.OrdinalIgnoreCase)) { var childProcessId = WindowProcess.GetProcessIDFromWindowHandle(hwnd); var childThreadId = WindowProcess.GetThreadIDFromWindowHandle(hwnd); From cf949331897542ee5c22e0f34f9a8234288743c3 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Thu, 13 Jan 2022 17:32:02 +0100 Subject: [PATCH 16/32] add window class to tool tip --- .../launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs index 1d842f1c6074..fc2e097acc93 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs @@ -51,7 +51,7 @@ public List Query(Query query) }, // For debugging you can remove the comment sign in the next line. - ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nProcess exists: {x.Result.ProcessInfo.DoesExist}\nIs full access denied: {x.Result.ProcessInfo.IsFullAccessDenied}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nIs window cloaked: {x.Result.IsCloaked}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), + ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nWindow class: {x.Result.ClassName}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nProcess exists: {x.Result.ProcessInfo.DoesExist}\nIs full access denied: {x.Result.ProcessInfo.IsFullAccessDenied}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nIs window cloaked: {x.Result.IsCloaked}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), }).ToList(); } From 1a457b12c30baf8e4e61453be2563a1e0c815228 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Thu, 13 Jan 2022 17:43:02 +0100 Subject: [PATCH 17/32] small change --- .../Components/WindowProcess.cs | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs index 342984a8b215..a3cd3eccc4a8 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs @@ -48,19 +48,45 @@ public string Name } /// - /// Gets a value indicating whether full access to the process is denied or not + /// Gets a value indicating whether the window belongs to an 'Universal Windows Platform (UWP)' process /// - public bool IsFullAccessDenied + public bool IsUwpApp { - get; private set; + get { return _isUwpApp; } } /// - /// Gets a value indicating whether the window belongs to an 'Universal Windows Platform (UWP)' process + /// Gets a value indicating whether the process exists on the machine /// - public bool IsUwpApp + public bool DoesExist { - get { return _isUwpApp; } + get + { + try + { + var p = Process.GetProcessById((int)ProcessID); + p.Dispose(); + return true; + } + catch (InvalidOperationException) + { + // Thrown when process not exist. + return false; + } + catch (ArgumentException) + { + // Thrown when process not exist. + return false; + } + } + } + + /// + /// Gets a value indicating whether full access to the process is denied or not + /// + public bool IsFullAccessDenied + { + get; private set; } /// @@ -125,32 +151,6 @@ public static string GetProcessNameFromProcessID(uint pid) } } - /// - /// Gets a value indicating whether the proces exists on the machine - /// - public bool DoesExist - { - get - { - try - { - var p = Process.GetProcessById((int)ProcessID); - p.Dispose(); - return true; - } - catch (InvalidOperationException) - { - // Thrown when process not exist. - return false; - } - catch (ArgumentException) - { - // Thrown when process not exist. - return false; - } - } - } - /// /// Gets a boolean value indicating whether the access to a process using the AllAccess flag is denied or not. /// From b65d9161eb3918cc6f7106de65bc3732c1bfcd72 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Thu, 13 Jan 2022 18:44:09 +0100 Subject: [PATCH 18/32] make nativeMethods static class --- .../Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs index a4b5892502cd..0246bb35def9 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs @@ -12,7 +12,7 @@ namespace Microsoft.Plugin.WindowWalker.Components /// /// Interop calls with helper layers /// - internal class NativeMethods + internal static class NativeMethods { public delegate bool CallBackPtr(IntPtr hwnd, IntPtr lParam); From 460c3ab661e665c85e51651ad2d86ea155935efc Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Thu, 13 Jan 2022 18:55:25 +0100 Subject: [PATCH 19/32] fix broken uwpApp property of WindowProcess class --- .../Components/Window.cs | 2 +- .../Components/WindowProcess.cs | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs index 182665a13768..2224327066d4 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs @@ -366,7 +366,7 @@ private static WindowProcess CreateWindowProcessInstance(IntPtr hWindow) var childProcessName = WindowProcess.GetProcessNameFromProcessID(childProcessId); // Update process info in cache - _handlesToProcessCache[hWindow] = new WindowProcess(childProcessId, childThreadId, childProcessName); + _handlesToProcessCache[hWindow].UpdateProcessInfo(childProcessId, childThreadId, childProcessName); return false; } else diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs index a3cd3eccc4a8..c9f6278224da 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs @@ -96,12 +96,23 @@ public bool IsFullAccessDenied /// New thread id. /// New process name. public WindowProcess(uint pid, uint tid, string name) + { + UpdateProcessInfo(pid, tid, name); + _isUwpApp = Name.ToUpperInvariant().Equals("APPLICATIONFRAMEHOST.EXE", StringComparison.Ordinal); + } + + /// + /// Updates the process information of the instance. + /// + /// New process id. + /// New thread id. + /// New process name. + public void UpdateProcessInfo(uint pid, uint tid, string name) { // TODO: Add verification as to wether the process id and thread id is valid ProcessID = pid; ThreadID = tid; Name = name; - _isUwpApp = Name.ToUpperInvariant().Equals("APPLICATIONFRAMEHOST.EXE", StringComparison.Ordinal); // Process can be elevated only if process id is not 0 (Dummy value on error) IsFullAccessDenied = (pid != 0) ? TestProcessAccessUsingAllAccessFlag(pid) : false; From 690676d75daa8ea5ba8d3016585262a27a6abc7b Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Thu, 13 Jan 2022 19:24:29 +0100 Subject: [PATCH 20/32] rename method --- .../Components/NativeMethods.cs | 12 ++++++------ .../Components/WindowProcess.cs | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs index 0246bb35def9..c2e264e23bb5 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs @@ -928,19 +928,19 @@ public static int GetLastWin32Error() } /// - /// Closes a process handle if it is not null. + /// Validate that the handle is not null and close it. /// - /// Process handle to close. + /// Handle to close. /// Zero if native method fails and nonzero if the native method succeeds. - public static bool CloseProcessHandle(IntPtr pHandle) + public static bool CloseHandleIfNotNull(IntPtr handle) { - if (pHandle == null) + if (handle == null) { - // Return true if nothing to close. + // Return true if there is nothing to close. return true; } - return CloseHandle(pHandle); + return CloseHandle(handle); } } } diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs index c9f6278224da..bb5b4a7f1b57 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs @@ -152,12 +152,12 @@ public static string GetProcessNameFromProcessID(uint pid) if (NativeMethods.GetProcessImageFileName(processHandle, processName, MaximumFileNameLength) != 0) { - NativeMethods.CloseProcessHandle(processHandle); + NativeMethods.CloseHandleIfNotNull(processHandle); return processName.ToString().Split('\\').Reverse().ToArray()[0]; } else { - NativeMethods.CloseProcessHandle(processHandle); + NativeMethods.CloseHandleIfNotNull(processHandle); return string.Empty; } } @@ -174,12 +174,12 @@ private static bool TestProcessAccessUsingAllAccessFlag(uint pid) if (NativeMethods.GetLastWin32Error() == 5) { // Error 5 = ERROR_ACCESS_DENIED - NativeMethods.CloseProcessHandle(processHandle); + NativeMethods.CloseHandleIfNotNull(processHandle); return true; } else { - NativeMethods.CloseProcessHandle(processHandle); + NativeMethods.CloseHandleIfNotNull(processHandle); return false; } } From 93efb4325d985c620c19008affa790e693e3fdb9 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Thu, 13 Jan 2022 19:28:27 +0100 Subject: [PATCH 21/32] Revert making NativeMethods class static. It contains instance members. --- .../Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs index c2e264e23bb5..625f8e7898fd 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs @@ -12,7 +12,7 @@ namespace Microsoft.Plugin.WindowWalker.Components /// /// Interop calls with helper layers /// - internal static class NativeMethods + internal class NativeMethods { public delegate bool CallBackPtr(IntPtr hwnd, IntPtr lParam); From 20b49a48e65f0cc33b71087b85e4bc8363ccf016 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Thu, 13 Jan 2022 19:49:48 +0100 Subject: [PATCH 22/32] improve loggign --- .../Microsoft.Plugin.WindowWalker/Components/Window.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs index 2224327066d4..b50600ef80be 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs @@ -9,6 +9,7 @@ using System.Globalization; using System.Text; using System.Threading.Tasks; +using Wox.Plugin.Logger; namespace Microsoft.Plugin.WindowWalker.Components { @@ -344,7 +345,8 @@ private static WindowProcess CreateWindowProcessInstance(IntPtr hWindow) } else { - Wox.Plugin.Logger.Log.Error($"Invalid process {processId} ({processName}) for window handle {hWindow}.", typeof(Window)); + // For the dwm process we can not receive the name. This is no problem because the window isn't part of result list. + Log.Debug($"Invalid process {processId} ({processName}) for window handle {hWindow}.", typeof(Window)); _handlesToProcessCache.Add(hWindow, new WindowProcess(0, 0, string.Empty)); } } From f2a3fa5ec68d1b07ab347beadc8f6e9160069cce Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Sun, 23 Jan 2022 11:18:19 +0100 Subject: [PATCH 23/32] fix merge mistakes --- .../Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs index 84e1da864e66..90b21ccbc886 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs @@ -111,7 +111,7 @@ public bool IsCloaked } /// - /// Gets a value indicating whether determines whether the specified window handle identifies an existing window. + /// Gets a value indicating whether the specified window handle identifies an existing window. /// public bool IsWindow { From ed768908010689c8215ee5519e6b3f742d735e0b Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Sun, 23 Jan 2022 11:44:17 +0100 Subject: [PATCH 24/32] fixes --- .../Components/NativeMethods.cs | 2 +- .../Components/WindowProcess.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs index 625f8e7898fd..ad3f126a7ddc 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs @@ -934,7 +934,7 @@ public static int GetLastWin32Error() /// Zero if native method fails and nonzero if the native method succeeds. public static bool CloseHandleIfNotNull(IntPtr handle) { - if (handle == null) + if (handle == IntPtr.Zero) { // Return true if there is nothing to close. return true; diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs index bb5b4a7f1b57..5c2c98362287 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs @@ -136,7 +136,7 @@ public static uint GetProcessIDFromWindowHandle(IntPtr hwnd) /// The thread ID public static uint GetThreadIDFromWindowHandle(IntPtr hwnd) { - var threadId = NativeMethods.GetWindowThreadProcessId(hwnd, out _); + uint threadId = NativeMethods.GetWindowThreadProcessId(hwnd, out _); return threadId; } @@ -152,12 +152,12 @@ public static string GetProcessNameFromProcessID(uint pid) if (NativeMethods.GetProcessImageFileName(processHandle, processName, MaximumFileNameLength) != 0) { - NativeMethods.CloseHandleIfNotNull(processHandle); + _ = NativeMethods.CloseHandleIfNotNull(processHandle); return processName.ToString().Split('\\').Reverse().ToArray()[0]; } else { - NativeMethods.CloseHandleIfNotNull(processHandle); + _ = NativeMethods.CloseHandleIfNotNull(processHandle); return string.Empty; } } @@ -169,17 +169,17 @@ public static string GetProcessNameFromProcessID(uint pid) /// True if denied and false if not. private static bool TestProcessAccessUsingAllAccessFlag(uint pid) { - var processHandle = NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.AllAccess, true, (int)pid); + IntPtr processHandle = NativeMethods.OpenProcess(NativeMethods.ProcessAccessFlags.AllAccess, true, (int)pid); if (NativeMethods.GetLastWin32Error() == 5) { // Error 5 = ERROR_ACCESS_DENIED - NativeMethods.CloseHandleIfNotNull(processHandle); + _ = NativeMethods.CloseHandleIfNotNull(processHandle); return true; } else { - NativeMethods.CloseHandleIfNotNull(processHandle); + _ = NativeMethods.CloseHandleIfNotNull(processHandle); return false; } } From 6924c1cafe13742a2647aaf90d71bdc9a5884074 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Sun, 23 Jan 2022 12:15:29 +0100 Subject: [PATCH 25/32] remove obsolete delegate --- .../Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs index 9faeb42f4a01..17a636659cea 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/OpenWindows.cs @@ -20,11 +20,6 @@ internal class OpenWindows /// private static readonly string _powerLauncherExe = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName); - /// - /// Delegate handler for open windows updates - /// - public delegate void OpenWindowsUpdateEventHandler(object sender, SearchController.SearchResultUpdateEventArgs e); - /// /// List of all the open windows /// From 906267dd38dea8c5967d03ccd579abb3f1d18fdc Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Sun, 23 Jan 2022 12:53:15 +0100 Subject: [PATCH 26/32] Improve SearchController to speed up search (#15561) --- .../Components/SearchController.cs | 23 ++++--------------- .../Microsoft.Plugin.WindowWalker/Main.cs | 2 +- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs index 826311de0738..c805f824c245 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Threading.Tasks; namespace Microsoft.Plugin.WindowWalker.Components { @@ -24,7 +23,7 @@ internal class SearchController /// /// Open window search results - /// private List searchMatches; /// @@ -95,16 +94,16 @@ private SearchController() /// /// Event handler for when the search text has been updated /// - public async Task UpdateSearchText(string searchText) + public void UpdateSearchText(string searchText) { SearchText = searchText; - await SyncOpenWindowsWithModelAsync().ConfigureAwait(false); + SyncOpenWindowsWithModel(); } /// /// Syncs the open windows with the OpenWindows Model /// - public async Task SyncOpenWindowsWithModelAsync() + public void SyncOpenWindowsWithModel() { System.Diagnostics.Debug.Print("Syncing WindowSearch result with OpenWindows Model"); @@ -116,24 +115,12 @@ public async Task SyncOpenWindowsWithModelAsync() } else { - searchMatches = await FuzzySearchOpenWindowsAsync(snapshotOfOpenWindows).ConfigureAwait(false); + searchMatches = FuzzySearchOpenWindows(snapshotOfOpenWindows); } OnSearchResultUpdateEventHandler?.Invoke(this, new SearchResultUpdateEventArgs()); } - /// - /// Redirecting method for Fuzzy searching - /// - /// what windows are open - /// Returns search results - private Task> FuzzySearchOpenWindowsAsync(List openWindows) - { - return Task.Run( - () => - FuzzySearchOpenWindows(openWindows)); - } - /// /// Search method that matches the title of windows with the user search text /// diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs index fc2e097acc93..e620b1a6f266 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs @@ -37,7 +37,7 @@ public List Query(Query query) } OpenWindows.Instance.UpdateOpenWindowsList(); - SearchController.Instance.UpdateSearchText(query.Search).Wait(); + SearchController.Instance.UpdateSearchText(query.Search); return _results.Select(x => new Result() { From d482ad2217b5313276e6d928aca4f3dd1e148bad Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Sun, 23 Jan 2022 13:56:55 +0100 Subject: [PATCH 27/32] add property to class --- .../Components/NativeMethods.cs | 3 +++ .../Components/WindowProcess.cs | 13 +++++++++++++ .../Plugins/Microsoft.Plugin.WindowWalker/Main.cs | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs index ad3f126a7ddc..17dfd875e8e4 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/NativeMethods.cs @@ -918,6 +918,9 @@ public enum ExtendedWindowStyles : uint [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CloseHandle(IntPtr hObject); + [DllImport("user32.dll")] + public static extern IntPtr GetShellWindow(); + /// /// Returns the last Win32 Error code thrown by a native method if enabled for this method. /// diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs index 5c2c98362287..1348708127e2 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs @@ -89,6 +89,19 @@ public bool IsFullAccessDenied get; private set; } + /// + /// Gets a value indicating whether this is the shell process or not + /// The shell process (like explorer.exe) hosts parts of the user interface (like taskbar, start menu, ...) + /// + public bool IsShellProcess + { + get + { + IntPtr hShellWindow = NativeMethods.GetShellWindow(); + return GetProcessIDFromWindowHandle(hShellWindow) == ProcessID; + } + } + /// /// Initializes a new instance of the class. /// diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs index e620b1a6f266..0b1730427951 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs @@ -51,7 +51,7 @@ public List Query(Query query) }, // For debugging you can remove the comment sign in the next line. - ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nWindow class: {x.Result.ClassName}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nProcess exists: {x.Result.ProcessInfo.DoesExist}\nIs full access denied: {x.Result.ProcessInfo.IsFullAccessDenied}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nIs window cloaked: {x.Result.IsCloaked}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), + ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nWindow class: {x.Result.ClassName}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nProcess exists: {x.Result.ProcessInfo.DoesExist}\nIs full access denied: {x.Result.ProcessInfo.IsFullAccessDenied}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nIs ShellProcess: {x.Result.ProcessInfo.IsShellProcess}\nIs window cloaked: {x.Result.IsCloaked}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), }).ToList(); } From f76c6805720443e8a26203286726c213c91afba8 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Sun, 23 Jan 2022 13:59:17 +0100 Subject: [PATCH 28/32] reorder code --- .../Components/WindowProcess.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs index 1348708127e2..5966d7f2d1e8 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/WindowProcess.cs @@ -55,6 +55,19 @@ public bool IsUwpApp get { return _isUwpApp; } } + /// + /// Gets a value indicating whether this is the shell process or not + /// The shell process (like explorer.exe) hosts parts of the user interface (like taskbar, start menu, ...) + /// + public bool IsShellProcess + { + get + { + IntPtr hShellWindow = NativeMethods.GetShellWindow(); + return GetProcessIDFromWindowHandle(hShellWindow) == ProcessID; + } + } + /// /// Gets a value indicating whether the process exists on the machine /// @@ -89,19 +102,6 @@ public bool IsFullAccessDenied get; private set; } - /// - /// Gets a value indicating whether this is the shell process or not - /// The shell process (like explorer.exe) hosts parts of the user interface (like taskbar, start menu, ...) - /// - public bool IsShellProcess - { - get - { - IntPtr hShellWindow = NativeMethods.GetShellWindow(); - return GetProcessIDFromWindowHandle(hShellWindow) == ProcessID; - } - } - /// /// Initializes a new instance of the class. /// From dbd9a6decdb71844ecb6d17bb360e9ea8137b1d7 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Sun, 23 Jan 2022 14:18:19 +0100 Subject: [PATCH 29/32] disable debug tool tip --- .../launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs index 0b1730427951..dc7e85236c91 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs @@ -51,7 +51,7 @@ public List Query(Query query) }, // For debugging you can remove the comment sign in the next line. - ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nWindow class: {x.Result.ClassName}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nProcess exists: {x.Result.ProcessInfo.DoesExist}\nIs full access denied: {x.Result.ProcessInfo.IsFullAccessDenied}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nIs ShellProcess: {x.Result.ProcessInfo.IsShellProcess}\nIs window cloaked: {x.Result.IsCloaked}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), + // ToolTipData = new ToolTipData(x.Result.Title, $"hWnd: {x.Result.Hwnd}\nWindow class: {x.Result.ClassName}\nProcess ID: {x.Result.ProcessInfo.ProcessID}\nThread ID: {x.Result.ProcessInfo.ThreadID}\nProcess: {x.Result.ProcessInfo.Name}\nProcess exists: {x.Result.ProcessInfo.DoesExist}\nIs full access denied: {x.Result.ProcessInfo.IsFullAccessDenied}\nIs uwp app: {x.Result.ProcessInfo.IsUwpApp}\nIs ShellProcess: {x.Result.ProcessInfo.IsShellProcess}\nIs window cloaked: {x.Result.IsCloaked}\nWindow cloak state: {x.Result.GetWindowCloakState()}"), }).ToList(); } From f56e8e0fd5a33695c6f34879503fdac1c5b7e2f1 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Sun, 23 Jan 2022 14:30:59 +0100 Subject: [PATCH 30/32] Update devdocs --- doc/devdocs/modules/launcher/plugins/windowwalker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/devdocs/modules/launcher/plugins/windowwalker.md b/doc/devdocs/modules/launcher/plugins/windowwalker.md index 9327e362a127..a1a188fa98ff 100644 --- a/doc/devdocs/modules/launcher/plugins/windowwalker.md +++ b/doc/devdocs/modules/launcher/plugins/windowwalker.md @@ -8,7 +8,7 @@ The window walker plugin matches the user entered query with the open windows on ### [`SearchController.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) - The [`SearchController`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs) encapsulates the functions needed to search and find matches. -- It is responsible for updating the search text and performing a fuzzy search on all the open windows in an asynchronous manner. +- It is responsible for updating the search text and performing a fuzzy search on all the open windows. ### [`Window.cs`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) - The [`Window`](/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/Window.cs) class represents a specific window and has functions to get the name of the window, the state of the window (whether it is visible or not), and the `SwitchTowindow` function which switches the desktop focus to the selected window. This action is performed when the user clicks on a window walker plugin result. From 80a456c86ba197f138f67b6f1daaaa691842e09b Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Mon, 24 Jan 2022 22:32:59 +0100 Subject: [PATCH 31/32] remove obsolete event handler --- .../Components/SearchController.cs | 12 ------------ .../Plugins/Microsoft.Plugin.WindowWalker/Main.cs | 11 ++--------- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs index c805f824c245..18740ce19bfb 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Components/SearchController.cs @@ -31,16 +31,6 @@ internal class SearchController /// private static SearchController instance; - /// - /// Delegate handler for open windows updates - /// - public delegate void SearchResultUpdateEventHandler(object sender, SearchResultUpdateEventArgs e); - - /// - /// Event raised when there is an update to the list of open windows - /// - public event SearchResultUpdateEventHandler OnSearchResultUpdateEventHandler; - /// /// Gets or sets the current search text /// @@ -117,8 +107,6 @@ public void SyncOpenWindowsWithModel() { searchMatches = FuzzySearchOpenWindows(snapshotOfOpenWindows); } - - OnSearchResultUpdateEventHandler?.Invoke(this, new SearchResultUpdateEventArgs()); } /// diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs index dc7e85236c91..dfcd9e61a912 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs @@ -13,8 +13,6 @@ namespace Microsoft.Plugin.WindowWalker { public class Main : IPlugin, IPluginI18n { - private static List _results = new List(); - private string IconPath { get; set; } private PluginInitContext Context { get; set; } @@ -25,7 +23,6 @@ public class Main : IPlugin, IPluginI18n static Main() { - SearchController.Instance.OnSearchResultUpdateEventHandler += SearchResultUpdated; OpenWindows.Instance.UpdateOpenWindowsList(); } @@ -38,8 +35,9 @@ public List Query(Query query) OpenWindows.Instance.UpdateOpenWindowsList(); SearchController.Instance.UpdateSearchText(query.Search); + List results = SearchController.Instance.SearchMatches; - return _results.Select(x => new Result() + return results.Select(x => new Result() { Title = x.Result.Title, IcoPath = IconPath, @@ -89,10 +87,5 @@ public string GetTranslatedPluginDescription() { return Properties.Resources.wox_plugin_windowwalker_plugin_description; } - - private static void SearchResultUpdated(object sender, SearchController.SearchResultUpdateEventArgs e) - { - _results = SearchController.Instance.SearchMatches; - } } } From bbfb538f525d3c8762a8bf3730a132191ae62e83 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Mon, 24 Jan 2022 22:39:23 +0100 Subject: [PATCH 32/32] update var name --- .../launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs index dfcd9e61a912..4d7072c507a6 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.WindowWalker/Main.cs @@ -35,9 +35,9 @@ public List Query(Query query) OpenWindows.Instance.UpdateOpenWindowsList(); SearchController.Instance.UpdateSearchText(query.Search); - List results = SearchController.Instance.SearchMatches; + List searchControllerResults = SearchController.Instance.SearchMatches; - return results.Select(x => new Result() + return searchControllerResults.Select(x => new Result() { Title = x.Result.Title, IcoPath = IconPath,