简体   繁体   English

使用单个 Windows 提示删除多个文件(文件系统)

[英]Delete Multiple Files with Single Windows Prompt (FileSystem)

I have a WPF application that displays files in a folder.我有一个显示文件夹中文件的 WPF 应用程序。 The user can select multiple files and select to delete them, currently I am using this logic with uses FileSystem from the VisualBasic.FileIO library:用户可以 select 多个文件和 select 来删除它们,目前我正在使用这个逻辑,使用 VisualBasic.FileIO 库中的文件系统:

foreach (Item item in items)
{
     if (item.IsDirectory)
     {
          FileSystem.DeleteDirectory(item.FullPath, UIOption.AllDialogs, RecycleOption.SendToRecycleBin);
     }
     else
     {
          FileSystem.DeleteFile(item.FullPath, UIOption.AllDialogs, RecycleOption.SendToRecycleBin);
     }
} 

The problem here is that if users have the Windows option "Display delete confirmation dialog" turned on:这里的问题是,如果用户打开了 Windows 选项“显示删除确认对话框”: 在此处输入图像描述

They get a Windows prompt for each file.他们得到每个文件的 Windows 提示。

I want them to get a single prompt like this:我希望他们得到一个这样的提示:

在此处输入图像描述

Is there a way to do this?有没有办法做到这一点?

Even if it involves a PInvoke of some WinAPI function?即使它涉及一些 WinAPI function 的 PInvoke?

With PInvoke, we can use SHFileOperation with the FO_DELETE function to send file system objects to the recycle bin.通过 PInvoke,我们可以使用SHFileOperationFO_DELETE function 将文件系统对象发送到回收站。 According to the documentation, we can send multiple paths at once by joining them with a NULL character:根据文档,我们可以通过使用 NULL 字符连接它们来一次发送多个路径:

Although this member is declared as a single null-terminated string, it is actually a buffer that can hold multiple null-delimited file names.尽管此成员被声明为单个以 null 结尾的字符串,但它实际上是一个可以容纳多个以 null 分隔的文件名的缓冲区。 Each file name is terminated by a single NULL character.每个文件名都以单个 NULL 字符结尾。 The last file name is terminated with a double NULL character ("\0\0") to indicate the end of the buffer.最后一个文件名以双字符 NULL ("\0\0") 结尾,表示缓冲区结束。

Instead of writing everything from scratch, let's use parts of the code in this answer and adjust it to work with multiple paths.让我们使用此答案中的部分代码并调整它以使用多个路径,而不是从头开始编写所有内容。 We will have something like this:我们会有这样的事情:

public class FileOperationAPIWrapper
{
    /// <summary>
    /// Possible flags for the SHFileOperation method.
    /// </summary>
    [Flags]
    public enum FileOperationFlags : ushort
    {
        /// <summary>
        /// Do not show a dialog during the process
        /// </summary>
        FOF_SILENT = 0x0004,
        /// <summary>
        /// Do not ask the user to confirm selection
        /// </summary>
        FOF_NOCONFIRMATION = 0x0010,
        /// <summary>
        /// Delete the file to the recycle bin.  (Required flag to send a file to the bin
        /// </summary>
        FOF_ALLOWUNDO = 0x0040,
        /// <summary>
        /// Do not show the names of the files or folders that are being recycled.
        /// </summary>
        FOF_SIMPLEPROGRESS = 0x0100,
        /// <summary>
        /// Surpress errors, if any occur during the process.
        /// </summary>
        FOF_NOERRORUI = 0x0400,
        /// <summary>
        /// Warn if files are too big to fit in the recycle bin and will need
        /// to be deleted completely.
        /// </summary>
        FOF_WANTNUKEWARNING = 0x4000,
    }

    /// <summary>
    /// File Operation Function Type for SHFileOperation
    /// </summary>
    public enum FileOperationType : uint
    {
        /// <summary>
        /// Move the objects
        /// </summary>
        FO_MOVE = 0x0001,
        /// <summary>
        /// Copy the objects
        /// </summary>
        FO_COPY = 0x0002,
        /// <summary>
        /// Delete (or recycle) the objects
        /// </summary>
        FO_DELETE = 0x0003,
        /// <summary>
        /// Rename the object(s)
        /// </summary>
        FO_RENAME = 0x0004,
    }

    /// <summary>
    /// SHFILEOPSTRUCT for SHFileOperation from COM
    /// </summary>
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    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);

    public static bool SendToRecycleBin(string path, FileOperationFlags flags)
    {
        return SendToRecycleBin(new[] { path }, flags);
    }

    public static bool SendToRecycleBin(IList<string> paths, FileOperationFlags flags)
    {
        try
        {
            var fs = new SHFILEOPSTRUCT
            {
                wFunc = FileOperationType.FO_DELETE,
                pFrom = string.Join("\0", paths) + '\0' + '\0',
                fFlags = FileOperationFlags.FOF_ALLOWUNDO | flags
            };
            SHFileOperation(ref fs);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }
}

Usage:用法:

FileOperationAPIWrapper.SendToRecycleBin(items,
    FileOperationAPIWrapper.FileOperationFlags.FOF_WANTNUKEWARNING);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM