// 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.Windows; using System.Windows.Input; using Microsoft.Plugin.WindowWalker.Properties; using Wox.Plugin; using Wox.Plugin.Logger; namespace Microsoft.Plugin.WindowWalker.Components { internal class ContextMenuHelper { /// /// Returns a list of all s for the selected . /// /// Selected result /// List of context menu results internal static List GetContextMenuResults(in Result result) { if (!(result?.ContextData is Window windowData)) { return new List(0); } var contextMenu = new List() { new ContextMenuResult { AcceleratorKey = Key.F4, AcceleratorModifiers = ModifierKeys.Control, FontFamily = "Segoe Fluent Icons,Segoe MDL2 Assets", Glyph = "\xE8BB", // E8B8 => Symbol: ChromeClose Title = $"{Resources.wox_plugin_windowwalker_Close} (Ctrl+F4)", Action = _ => { if (!windowData.IsWindow) { Log.Debug($"Cannot close the window '{windowData.Title}' ({windowData.Hwnd}), because it doesn't exist.", typeof(ContextMenuHelper)); return false; } windowData.CloseThisWindow(); return !WindowWalkerSettings.Instance.OpenAfterKillAndClose; }, }, }; // Hide menu if Explorer.exe is the shell process or the process name is ApplicationFrameHost.exe // In the first case we would crash the windows ui and in the second case we would kill the generic process for uwp apps. if (!windowData.Process.IsShellProcess && !(windowData.Process.IsUwpApp && string.Equals(windowData.Process.Name, "ApplicationFrameHost.exe", StringComparison.OrdinalIgnoreCase)) && !(windowData.Process.IsFullAccessDenied && WindowWalkerSettings.Instance.HideKillProcessOnElevatedProcesses)) { contextMenu.Add(new ContextMenuResult { AcceleratorKey = Key.Delete, AcceleratorModifiers = ModifierKeys.Control, FontFamily = "Segoe Fluent Icons,Segoe MDL2 Assets", Glyph = "\xE74D", // E74D => Symbol: Delete Title = $"{Resources.wox_plugin_windowwalker_Kill} (Ctrl+Delete)", Action = _ => KillProcessCommand(windowData), }); } return contextMenu; } /// /// Method to initiate killing the process of a window /// /// Window data /// True if the PT Run window should close; otherwise, false. private static bool KillProcessCommand(Window window) { // Validate process if (!window.IsWindow || !window.Process.DoesExist || !window.Process.Name.Equals(WindowProcess.GetProcessNameFromProcessID(window.Process.ProcessID), StringComparison.Ordinal)) { Log.Debug($"Cannot kill process '{window.Process.Name}' ({window.Process.ProcessID}) of the window '{window.Title}' ({window.Hwnd}), because it doesn't exist.", typeof(ContextMenuHelper)); return false; } // Request user confirmation if (WindowWalkerSettings.Instance.ConfirmKillProcess) { string messageBody = $"{Resources.wox_plugin_windowwalker_KillMessage}\n" + $"{window.Process.Name} ({window.Process.ProcessID})\n\n" + $"{(window.Process.IsUwpApp ? Resources.wox_plugin_windowwalker_KillMessageUwp : Resources.wox_plugin_windowwalker_KillMessageQuestion)}"; MessageBoxResult messageBoxResult = MessageBox.Show( messageBody, Resources.wox_plugin_windowwalker_plugin_name + " - " + Resources.wox_plugin_windowwalker_KillMessageTitle, MessageBoxButton.YesNo, MessageBoxImage.Warning); if (messageBoxResult == MessageBoxResult.No) { return false; } } // Kill process window.Process.KillThisProcess(WindowWalkerSettings.Instance.KillProcessTree); return !WindowWalkerSettings.Instance.OpenAfterKillAndClose; } } }