/ src / modules / launcher / Plugins / Microsoft.PowerToys.Run.Plugin.System / Components / ResultHelper.cs
ResultHelper.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 5 using System; 6 using System.Collections.Generic; 7 using System.Threading.Tasks; 8 using System.Windows; 9 using System.Windows.Input; 10 11 using Microsoft.PowerToys.Run.Plugin.System.Properties; 12 using Wox.Plugin; 13 using Wox.Plugin.Common.Win32; 14 using Wox.Plugin.Logger; 15 16 namespace Microsoft.PowerToys.Run.Plugin.System.Components 17 { 18 internal static class ResultHelper 19 { 20 private static bool executingEmptyRecycleBinTask; 21 22 internal static bool ExecuteCommand(bool confirm, string confirmationMessage, Action command) 23 { 24 if (confirm) 25 { 26 MessageBoxResult messageBoxResult = MessageBox.Show( 27 confirmationMessage, 28 Resources.Microsoft_plugin_sys_confirmation, 29 MessageBoxButton.YesNo, 30 MessageBoxImage.Warning); 31 32 if (messageBoxResult == MessageBoxResult.No) 33 { 34 return false; 35 } 36 } 37 38 command(); 39 return true; 40 } 41 42 internal static bool CopyToClipBoard(in string text) 43 { 44 try 45 { 46 Clipboard.Clear(); 47 Clipboard.SetText(text); 48 return true; 49 } 50 catch (Exception exception) 51 { 52 Log.Exception("Can't copy to clipboard", exception, typeof(ResultHelper)); 53 return false; 54 } 55 } 56 57 internal static async void EmptyRecycleBinAsync(bool settingEmptyRBSuccesMsg) 58 { 59 if (executingEmptyRecycleBinTask) 60 { 61 _ = MessageBox.Show(Resources.Microsoft_plugin_sys_RecycleBin_EmptyTaskRunning, "Plugin: " + Resources.Microsoft_plugin_sys_plugin_name, MessageBoxButton.OK, MessageBoxImage.Information); 62 return; 63 } 64 65 await Task.Run(() => EmptyRecycleBinTask(settingEmptyRBSuccesMsg)); 66 } 67 68 internal static List<ContextMenuResult> GetContextMenuForResult(Result result, bool settingEmptyRBSuccesMsg) 69 { 70 var contextMenu = new List<ContextMenuResult>(); 71 72 if (!(result?.ContextData is SystemPluginContext contextData)) 73 { 74 return contextMenu; 75 } 76 77 if (contextData.Type == ResultContextType.NetworkAdapterInfo) 78 { 79 contextMenu.Add(new ContextMenuResult() 80 { 81 AcceleratorKey = Key.C, 82 AcceleratorModifiers = ModifierKeys.Control, 83 FontFamily = "Segoe Fluent Icons,Segoe MDL2 Assets", 84 Glyph = "\xE8C8", // E8C8 => Symbol: Copy 85 Title = Resources.Microsoft_plugin_sys_CopyDetails, 86 Action = _ => CopyToClipBoard(contextData.Data), 87 }); 88 } 89 90 if (contextData.Type == ResultContextType.RecycleBinCommand) 91 { 92 contextMenu.Add(new ContextMenuResult() 93 { 94 AcceleratorKey = Key.Delete, 95 AcceleratorModifiers = ModifierKeys.Shift, // Shift+Delete is the common key for deleting without recycle bin 96 FontFamily = "Segoe Fluent Icons,Segoe MDL2 Assets", 97 Glyph = "\xE74D", // E74D => Symbol: Delete 98 Title = Resources.Microsoft_plugin_sys_RecycleBin_contextMenu, 99 Action = _ => 100 { 101 EmptyRecycleBinAsync(settingEmptyRBSuccesMsg); 102 return true; 103 }, 104 }); 105 } 106 107 return contextMenu; 108 } 109 110 /// <summary> 111 /// Method to process the empty recycle bin command in a separate task 112 /// </summary> 113 private static void EmptyRecycleBinTask(bool settingEmptyRBSuccesMsg) 114 { 115 executingEmptyRecycleBinTask = true; 116 117 // https://learn.microsoft.com/windows/win32/api/shellapi/nf-shellapi-shemptyrecyclebina/ 118 // http://www.pinvoke.net/default.aspx/shell32/SHEmptyRecycleBin.html/ 119 // If the recycle bin is already empty, it will return -2147418113 (0x8000FFFF (E_UNEXPECTED)) 120 // If the user canceled the deletion task it will return 2147943623 (0x800704C7 (E_CANCELLED - The operation was canceled by the user.)) 121 // On success it will return 0 (S_OK) 122 var result = NativeMethods.SHEmptyRecycleBin(IntPtr.Zero, 0); 123 if (result == (uint)HRESULT.E_UNEXPECTED) 124 { 125 _ = MessageBox.Show(Resources.Microsoft_plugin_sys_RecycleBin_IsEmpty, "Plugin: " + Resources.Microsoft_plugin_sys_plugin_name, MessageBoxButton.OK, MessageBoxImage.Information); 126 } 127 else if (result != (uint)HRESULT.S_OK && result != (uint)HRESULT.E_CANCELLED) 128 { 129 var errorDesc = Win32Helpers.MessageFromHResult((int)result); 130 var name = "Plugin: " + Resources.Microsoft_plugin_sys_plugin_name; 131 var message = $"{Resources.Microsoft_plugin_sys_RecycleBin_ErrorMsg} {errorDesc}"; 132 Log.Error(message + " - Please refer to https://msdn.microsoft.com/library/windows/desktop/aa378137 for more information.", typeof(Commands)); 133 _ = MessageBox.Show(message, name, MessageBoxButton.OK, MessageBoxImage.Error); 134 } 135 136 if (result == (uint)HRESULT.S_OK && settingEmptyRBSuccesMsg) 137 { 138 _ = MessageBox.Show(Resources.Microsoft_plugin_sys_RecycleBin_EmptySuccessMessage, "Plugin: " + Resources.Microsoft_plugin_sys_plugin_name, MessageBoxButton.OK, MessageBoxImage.Information); 139 } 140 141 executingEmptyRecycleBinTask = false; 142 } 143 } 144 }