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  }