private void OnRemove(ShellOperationEventArgs e) { if (e.Item.IsFolder) { // delete a key using (var key = OpenKey(true)) { if (key != null) { key.DeleteSubKeyTree(e.Item.DisplayName, false); } } e.HResult = ShellUtilities.S_OK; return; } // delete a value using (var key = OpenKey(true)) { if (key != null) { var keyName = ((RegistryValueItem)e.Item).KeyName; key.DeleteValue(keyName, false); // deleting the default value will in fact unset its value, so we don't want explorer to remove the item visually if (string.IsNullOrEmpty(keyName)) { const int COPYENGINE_E_USER_CANCELLED = unchecked ((int)0x80270000); e.HResult = COPYENGINE_E_USER_CANCELLED; e.Item.NotifyUpdate(); } } } e.HResult = ShellUtilities.S_OK; }
private async void OnRename(ShellOperationEventArgs e) { if (e.Item.IsFolder) { // rename a key using (var key = OpenKey(true)) { if (key != null) { var path = System.IO.Path.Combine(Path ?? string.Empty, e.Item.DisplayName); RegRenameKey(key.Handle, path, e.NewName); e.NewId = new StringKeyShellItemId(e.NewName); e.Item.NotifyRename(e.NewId); e.HResult = ShellUtilities.S_OK; } } return; } // rename a value (delete + set) using (var key = OpenKey(true)) { if (key != null) { if (key.GetValueNames().Contains(e.NewName, StringComparer.OrdinalIgnoreCase)) { await WindowsUtilities.DoModelessAsync(() => { MessageBox.Show(new Win32Window(e.HwndOwner), "The Registry Folder cannot rename '" + e.Item.DisplayName + "'. The specified value name already exists. Type another name and try again.", "Registry Folder", MessageBoxButtons.OK, MessageBoxIcon.Error); }); } else { var value = key.GetValue(e.Item.DisplayName); if (value == null) { await WindowsUtilities.DoModelessAsync(() => { MessageBox.Show(new Win32Window(e.HwndOwner), "The Registry Folder cannot rename '" + e.Item.DisplayName + "'. The specified value name does not exists. Refresh the view and try again.", "Registry Folder", MessageBoxButtons.OK, MessageBoxIcon.Error); }); } else { key.SetValue(e.NewName, value); key.DeleteValue(e.Item.DisplayName, false); e.NewId = new StringKeyShellItemId(e.NewName); e.HResult = ShellUtilities.S_OK; e.Item.Parent?.NotifyUpdate(); } } } } }
protected override void OnOperate(ShellOperationEventArgs e) { switch (e.Operation) { case ShellOperation.SetNameOf: case ShellOperation.RenameItem: OnRename(e); break; case ShellOperation.RemoveItem: OnRemove(e); break; } }
protected override void OnOperate(ShellOperationEventArgs e) { Console.WriteLine("OnOperate " + e.Operation); }
protected override void OnOperate(ShellOperationEventArgs e) { // some advanced errors number can be found in %ProgramFiles(x86)%\Windows Kits\10\Include\<SDK Version>\um\sherrors.h (for example with SDK Version = 10.0.19041.0) var item = (e.Item as IObjectWithApiItem)?.ApiItem; switch (e.Operation) { case ShellOperation.RecycleItem: // our recycle bin is only local (a server side recycle bin may be better, but not implemented here) if (e.Item is IObjectWithApiItem si && e.Item.FileSystemPath != null) { // we copy the file in an accessible folder so the user will be able to get to it when pulling out from recycle bin var recycledPath = si.ApiItem.Recycle(); using (var fo = new FileOperation()) { fo.SetOperationFlags(FOF.FOFX_RECYCLEONDELETE); fo.DeleteItem(recycledPath); fo.PerformOperations(); } if (item.DeleteAsync(e.Item.FileSystemPath, new DeleteOptions { Recursive = true }).Result) { // tell the Shell not to process children (in case of a folder), as the server did it (or failed) const int COPYENGINE_S_DONT_PROCESS_CHILDREN = 0x00270008; e.HResult = COPYENGINE_S_DONT_PROCESS_CHILDREN; NotifyUpdate(); } else { // we can only reuse well-known error, for example e.HResult = ShellUtilities.ERROR_RETRY; } } break; case ShellOperation.RemoveItem: if (item.DeleteAsync(e.Item.FileSystemPath, new DeleteOptions { Recursive = true }).Result) { // tell the Shell not to process children (in case of a folder), as the server did it (or failed) const int COPYENGINE_S_DONT_PROCESS_CHILDREN = 0x00270008; e.HResult = COPYENGINE_S_DONT_PROCESS_CHILDREN; NotifyUpdate(); } else { // we can only reuse well-known error, for example e.HResult = ShellUtilities.ERROR_RETRY; } break; case ShellOperation.RenameItem: case ShellOperation.SetNameOf: var result = item.RenameAsync(e.NewName, e.Item.FileSystemPath).Result; if (result != null) { e.HResult = ShellUtilities.S_OK; NotifyUpdate(); } else { // we can only reuse well-known error, for example e.HResult = ShellUtilities.ERROR_RETRY; } break; } base.OnOperate(e); }