/ src / modules / launcher / Plugins / Microsoft.Plugin.WindowWalker / Components / ContextMenuHelper.cs
ContextMenuHelper.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 using System; 5 using System.Collections.Generic; 6 using System.Windows; 7 using System.Windows.Input; 8 9 using Microsoft.Plugin.WindowWalker.Properties; 10 using Wox.Plugin; 11 using Wox.Plugin.Logger; 12 13 namespace Microsoft.Plugin.WindowWalker.Components 14 { 15 internal class ContextMenuHelper 16 { 17 /// <summary> 18 /// Returns a list of all <see cref="ContextMenuResult"/>s for the selected <see cref="Result"/>. 19 /// </summary> 20 /// <param name="result">Selected result</param> 21 /// <returns>List of context menu results</returns> 22 internal static List<ContextMenuResult> GetContextMenuResults(in Result result) 23 { 24 if (!(result?.ContextData is Window windowData)) 25 { 26 return new List<ContextMenuResult>(0); 27 } 28 29 var contextMenu = new List<ContextMenuResult>() 30 { 31 new ContextMenuResult 32 { 33 AcceleratorKey = Key.F4, 34 AcceleratorModifiers = ModifierKeys.Control, 35 FontFamily = "Segoe Fluent Icons,Segoe MDL2 Assets", 36 Glyph = "\xE8BB", // E8B8 => Symbol: ChromeClose 37 Title = $"{Resources.wox_plugin_windowwalker_Close} (Ctrl+F4)", 38 Action = _ => 39 { 40 if (!windowData.IsWindow) 41 { 42 Log.Debug($"Cannot close the window '{windowData.Title}' ({windowData.Hwnd}), because it doesn't exist.", typeof(ContextMenuHelper)); 43 return false; 44 } 45 46 windowData.CloseThisWindow(); 47 48 return !WindowWalkerSettings.Instance.OpenAfterKillAndClose; 49 }, 50 }, 51 }; 52 53 // Hide menu if Explorer.exe is the shell process or the process name is ApplicationFrameHost.exe 54 // In the first case we would crash the windows ui and in the second case we would kill the generic process for uwp apps. 55 if (!windowData.Process.IsShellProcess && !(windowData.Process.IsUwpApp && string.Equals(windowData.Process.Name, "ApplicationFrameHost.exe", StringComparison.OrdinalIgnoreCase)) 56 && !(windowData.Process.IsFullAccessDenied && WindowWalkerSettings.Instance.HideKillProcessOnElevatedProcesses)) 57 { 58 contextMenu.Add(new ContextMenuResult 59 { 60 AcceleratorKey = Key.Delete, 61 AcceleratorModifiers = ModifierKeys.Control, 62 FontFamily = "Segoe Fluent Icons,Segoe MDL2 Assets", 63 Glyph = "\xE74D", // E74D => Symbol: Delete 64 Title = $"{Resources.wox_plugin_windowwalker_Kill} (Ctrl+Delete)", 65 Action = _ => KillProcessCommand(windowData), 66 }); 67 } 68 69 return contextMenu; 70 } 71 72 /// <summary> 73 /// Method to initiate killing the process of a window 74 /// </summary> 75 /// <param name="window">Window data</param> 76 /// <returns>True if the PT Run window should close; otherwise, false.</returns> 77 private static bool KillProcessCommand(Window window) 78 { 79 // Validate process 80 if (!window.IsWindow || !window.Process.DoesExist || !window.Process.Name.Equals(WindowProcess.GetProcessNameFromProcessID(window.Process.ProcessID), StringComparison.Ordinal)) 81 { 82 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)); 83 return false; 84 } 85 86 // Request user confirmation 87 if (WindowWalkerSettings.Instance.ConfirmKillProcess) 88 { 89 string messageBody = $"{Resources.wox_plugin_windowwalker_KillMessage}\n" 90 + $"{window.Process.Name} ({window.Process.ProcessID})\n\n" 91 + $"{(window.Process.IsUwpApp ? Resources.wox_plugin_windowwalker_KillMessageUwp : Resources.wox_plugin_windowwalker_KillMessageQuestion)}"; 92 MessageBoxResult messageBoxResult = MessageBox.Show( 93 messageBody, 94 Resources.wox_plugin_windowwalker_plugin_name + " - " + Resources.wox_plugin_windowwalker_KillMessageTitle, 95 MessageBoxButton.YesNo, 96 MessageBoxImage.Warning); 97 98 if (messageBoxResult == MessageBoxResult.No) 99 { 100 return false; 101 } 102 } 103 104 // Kill process 105 window.Process.KillThisProcess(WindowWalkerSettings.Instance.KillProcessTree); 106 return !WindowWalkerSettings.Instance.OpenAfterKillAndClose; 107 } 108 } 109 }