// 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. using System; using System.Collections.Generic; using System.Linq; using Microsoft.Plugin.WindowWalker.Properties; using Wox.Infrastructure; using Wox.Plugin; namespace Microsoft.Plugin.WindowWalker.Components { /// /// Helper class to work with results /// internal static class ResultHelper { /// /// Returns a list of all results for the query. /// /// List with all search controller matches /// The path to the result icon /// List of results internal static List GetResultList(List searchControllerResults, bool isKeywordSearch, string icon, string infoIcon) { if (searchControllerResults == null || searchControllerResults.Count == 0) { return new List(); } List resultsList = new List(searchControllerResults.Count); bool addExplorerInfo = searchControllerResults.Any(x => string.Equals(x.Result.Process.Name, "explorer.exe", StringComparison.OrdinalIgnoreCase) && x.Result.Process.IsShellProcess); // Process each SearchResult to convert it into a Result. // Using parallel processing if the operation is CPU-bound and the list is large. resultsList = searchControllerResults .AsParallel() .Select(x => CreateResultFromSearchResult(x, icon)) .ToList(); if (addExplorerInfo && isKeywordSearch && !WindowWalkerSettings.Instance.HideExplorerSettingInfo) { resultsList.Add(GetExplorerInfoResult(infoIcon)); } return resultsList; } /// /// Creates a Result object from a given SearchResult. /// /// The SearchResult object to convert. /// The path to the icon that should be used for the Result. /// A Result object populated with data from the SearchResult. private static Result CreateResultFromSearchResult(SearchResult searchResult, string icon) { return new Result { Title = searchResult.Result.Title, IcoPath = icon, SubTitle = GetSubtitle(searchResult.Result), ContextData = searchResult.Result, Action = c => { searchResult.Result.SwitchToWindow(); return true; }, Score = searchResult.Score, // For debugging you can set the second parameter to true to see more information. ToolTipData = GetToolTip(searchResult.Result, false), }; } /// /// Returns the subtitle for a result /// /// The window properties of the result /// String with the subtitle private static string GetSubtitle(Window window) { if (window == null || !(window is Window)) { return string.Empty; } string subtitleText = Resources.wox_plugin_windowwalker_Running + ": " + window.Process.Name; if (WindowWalkerSettings.Instance.SubtitleShowPid) { subtitleText += $" ({window.Process.ProcessID})"; } if (!window.Process.IsResponding) { subtitleText += $" [{Resources.wox_plugin_windowwalker_NotResponding}]"; } if (WindowWalkerSettings.Instance.SubtitleShowDesktopName && Main.VirtualDesktopHelperInstance.GetDesktopCount() > 1) { subtitleText += $" - {Resources.wox_plugin_windowwalker_Desktop}: {window.Desktop.Name}"; } return subtitleText; } /// /// Returns the tool tip for a result /// /// The window properties of the result /// Value indicating if a detailed debug tooltip should be returned /// Tooltip for the result or null of failure private static ToolTipData GetToolTip(Window window, bool debugToolTip) { if (window == null || !(window is Window)) { return null; } if (!debugToolTip) { string text = $"{Resources.wox_plugin_windowwalker_Process}: {window.Process.Name}"; text += $"\n{Resources.wox_plugin_windowwalker_ProcessId}: {window.Process.ProcessID}"; if (Main.VirtualDesktopHelperInstance.GetDesktopCount() > 1) { text += $"\n{Resources.wox_plugin_windowwalker_Desktop}: {window.Desktop.Name}"; if (!window.Desktop.IsAllDesktopsView) { text += $" ({Resources.wox_plugin_windowwalker_Number} {window.Desktop.Number})"; } } return new ToolTipData(window.Title, text); } else { string text = $"hWnd: {window.Hwnd}\n" + $"Window class: {window.ClassName}\n" + $"Process ID: {window.Process.ProcessID}\n" + $"Thread ID: {window.Process.ThreadID}\n" + $"Process: {window.Process.Name}\n" + $"Process exists: {window.Process.DoesExist}\n" + $"Is full access denied: {window.Process.IsFullAccessDenied}\n" + $"Is uwp app: {window.Process.IsUwpApp}\n" + $"Is ShellProcess: {window.Process.IsShellProcess}\n" + $"Is window cloaked: {window.IsCloaked}\n" + $"Window cloak state: {window.GetWindowCloakState()}\n" + $"Desktop id: {window.Desktop.Id}\n" + $"Desktop name: {window.Desktop.Name}\n" + $"Desktop number: {window.Desktop.Number}\n" + $"Desktop is visible: {window.Desktop.IsVisible}\n" + $"Desktop position: {window.Desktop.Position}\n" + $"Is AllDesktops view: {window.Desktop.IsAllDesktopsView}\n" + $"Responding: {window.Process.IsResponding}"; return new ToolTipData(window.Title, text); } } /// /// Returns an information result about the explorer setting /// /// The path to the info icon. /// An object of the type with the information. private static Result GetExplorerInfoResult(string iIcon) { return new Result() { Title = Resources.wox_plugin_windowwalker_ExplorerInfoTitle, IcoPath = iIcon, SubTitle = Resources.wox_plugin_windowwalker_ExplorerInfoSubTitle, Action = c => { Helper.OpenInShell("rundll32.exe", "shell32.dll,Options_RunDLL 7"); // "shell32.dll,Options_RunDLL 7" opens the view tab in folder options of explorer. return true; }, Score = 100_000, }; } } }