From 37d94613045ab369a8dee2b2c0aa9b1c8f5f8495 Mon Sep 17 00:00:00 2001 From: morkt Date: Fri, 8 Aug 2014 14:08:49 +0400 Subject: [PATCH] implemented deletion of multiple files into recycle bin. --- MainWindow.xaml.cs | 14 +---- Shell.cs | 141 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 143 insertions(+), 12 deletions(-) diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index 4efd35ed..d07cd36b 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -838,21 +838,13 @@ namespace GARbro.GUI } else { - var rc = MessageBox.Show (this, guiStrings.MsgConfirmDeleteFiles, guiStrings.TextDeleteFiles, - MessageBoxButton.YesNo, MessageBoxImage.Question); - if (MessageBoxResult.Yes != rc) - return; int count = 0; StopWatchDirectoryChanges (); try { - Trace.WriteLine (string.Format ("deleting multiple files in {0}", CurrentPath), "DeleteItemExec"); - foreach (var entry in items) - { - string item_name = Path.Combine (CurrentPath, entry.Name); - FileSystem.DeleteFile (item_name); - ++count; - } + var file_list = items.Select (entry => Path.Combine (CurrentPath, entry.Name)); + GARbro.Shell.File.Delete (file_list); + count = file_list.Count(); } catch { diff --git a/Shell.cs b/Shell.cs index e251e9c8..b75598cc 100644 --- a/Shell.cs +++ b/Shell.cs @@ -25,7 +25,8 @@ using System; using System.IO; -//using System.Text; +using System.Text; +using System.Collections.Generic; using System.Runtime.InteropServices; namespace GARbro.Shell @@ -58,6 +59,144 @@ namespace GARbro.Shell { return Marshal.GetLastWin32Error(); } + + /// + /// Possible flags for the SHFileOperation method. + /// + [Flags] + public enum FileOperationFlags : ushort + { + /// + /// Do not show a dialog during the process + /// + FOF_SILENT = 0x0004, + /// + /// Do not ask the user to confirm selection + /// + FOF_NOCONFIRMATION = 0x0010, + /// + /// Delete the file to the recycle bin. (Required flag to send a file to the bin + /// + FOF_ALLOWUNDO = 0x0040, + /// + /// Do not show the names of the files or folders that are being recycled. + /// + FOF_SIMPLEPROGRESS = 0x0100, + /// + /// Surpress errors, if any occur during the process. + /// + FOF_NOERRORUI = 0x0400, + /// + /// Warn if files are too big to fit in the recycle bin and will need + /// to be deleted completely. + /// + FOF_WANTNUKEWARNING = 0x4000, + } + + /// + /// File Operation Function Type for SHFileOperation + /// + public enum FileOperationType : uint + { + /// + /// Move the objects + /// + FO_MOVE = 0x0001, + /// + /// Copy the objects + /// + FO_COPY = 0x0002, + /// + /// Delete (or recycle) the objects + /// + FO_DELETE = 0x0003, + /// + /// Rename the object(s) + /// + FO_RENAME = 0x0004, + } + + /// + /// SHFILEOPSTRUCT for SHFileOperation from COM + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)] + private struct SHFILEOPSTRUCT + { + + public IntPtr hwnd; + [MarshalAs(UnmanagedType.U4)] + public FileOperationType wFunc; + public string pFrom; + public string pTo; + public FileOperationFlags fFlags; + [MarshalAs(UnmanagedType.Bool)] + public bool fAnyOperationsAborted; + public IntPtr hNameMappings; + public string lpszProgressTitle; + } + + [DllImport("shell32.dll", CharSet = CharSet.Auto)] + private static extern int SHFileOperation (ref SHFILEOPSTRUCT FileOp); + + /// + /// Send file to recycle bin + /// + /// Location of directory or file to recycle + /// FileOperationFlags to add in addition to FOF_ALLOWUNDO + public static bool Delete (string path, FileOperationFlags flags) + { + var fs = new SHFILEOPSTRUCT + { + wFunc = FileOperationType.FO_DELETE, + pFrom = path + '\0' + '\0', + fFlags = FileOperationFlags.FOF_ALLOWUNDO | flags + }; + return 0 == SHFileOperation (ref fs); + } + + public static bool Delete (IEnumerable file_list, FileOperationFlags flags) + { + var files = new StringBuilder(); + foreach (var file in file_list) + { + files.Append (file); + files.Append ('\0'); + } + if (0 == files.Length) + return false; + files.Append ('\0'); + var fs = new SHFILEOPSTRUCT + { + wFunc = FileOperationType.FO_DELETE, + pFrom = files.ToString(), + fFlags = FileOperationFlags.FOF_ALLOWUNDO | flags + }; + return 0 == SHFileOperation (ref fs); + } + + public static bool Delete (IEnumerable file_list) + { + return Delete (file_list, FileOperationFlags.FOF_WANTNUKEWARNING); + } + + /// + /// Send file to recycle bin. Display dialog, display warning if files are too big to fit (FOF_WANTNUKEWARNING) + /// + /// Location of directory or file to recycle + public static bool Delete (string path) + { + return Delete (path, FileOperationFlags.FOF_NOCONFIRMATION | FileOperationFlags.FOF_WANTNUKEWARNING); + } + + /// + /// Send file silently to recycle bin. Surpress dialog, surpress errors, delete if too large. + /// + /// Location of directory or file to recycle + public static bool MoveToRecycleBin (string path) + { + return Delete (path, FileOperationFlags.FOF_NOCONFIRMATION | FileOperationFlags.FOF_NOERRORUI | FileOperationFlags.FOF_SILENT); + + } } public class TemporaryFile : IDisposable