【问题标题】:Send a File to the Recycle Bin将文件发送到回收站
【发布时间】:2010-07-19 15:23:19
【问题描述】:

目前我正在使用以下功能

file.Delete();

但是如何使用此功能将文件发送到回收站而不是直接删除呢?

【问题讨论】:

标签: c# recycle-bin


【解决方案1】:

使用FileSystem.DeleteFile 并指定正确的RecycleOption

虽然这适用于 UI 交互式应用程序,但它不适用于非 UI 交互式应用程序,如 Windows 服务应用程序。

【讨论】:

  • @noldorin 这是一个完美的解决方案,不值得反对。我想了解为什么访问 VisualBasic 库是“丑陋的”。
  • @noldorin:尤其是在这种情况下,Microsoft.VisualBasic.FileIO.FileSystem 与此处使用SHFileOperation 发布的示例基本相同。
  • @Noldorin:丑陋,是吧?对我来说,WinAPI 的方式更丑陋——而且,你最好把事情搞砸。我个人不喜欢 VB syntax 但在程序集中它只是 IL 所以我不介意。 VB 程序集顺便调用了相同的 WinAPI 函数。
  • @Noldorin:过时了?您是否偶然将程序集误认为Microsoft.VisualBasic.Compatibility?我避免的那个。它似乎不会很快被弃用(它用于 RDL 报告引擎等)。
  • @Noldorin:使用内置框架程序集看起来比使用硬样式映射到 shell32.dll 更好。使用框架程序集,您可以获得可移植的更改并获得以后的演变。映射到系统库,您随时都有可能被淘汰...
【解决方案2】:

注意:这也不适用于 Windows 服务等非 UI 交互应用程序

这个包装器可以提供你需要的功能:

using System.Runtime.InteropServices;

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);

        /// <summary>
        /// Send file to recycle bin
        /// </summary>
        /// <param name="path">Location of directory or file to recycle</param>
        /// <param name="flags">FileOperationFlags to add in addition to FOF_ALLOWUNDO</param>
        public static bool Send(string path, FileOperationFlags flags)
        {
            try
            {
                var fs = new SHFILEOPSTRUCT
                                        {
                                            wFunc = FileOperationType.FO_DELETE,
                                            pFrom = path + '\0' + '\0',
                                            fFlags = FileOperationFlags.FOF_ALLOWUNDO | flags
                                        };
                SHFileOperation(ref fs);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Send file to recycle bin.  Display dialog, display warning if files are too big to fit (FOF_WANTNUKEWARNING)
        /// </summary>
        /// <param name="path">Location of directory or file to recycle</param>
        public static bool Send(string path)
        {
            return Send(path, FileOperationFlags.FOF_NOCONFIRMATION | FileOperationFlags.FOF_WANTNUKEWARNING);
        }

        /// <summary>
        /// Send file silently to recycle bin.  Surpress dialog, surpress errors, delete if too large.
        /// </summary>
        /// <param name="path">Location of directory or file to recycle</param>
        public static bool MoveToRecycleBin(string path)
        {
            return Send(path, FileOperationFlags.FOF_NOCONFIRMATION | FileOperationFlags.FOF_NOERRORUI | FileOperationFlags.FOF_SILENT);

        }

        private static bool deleteFile(string path, FileOperationFlags flags)
        {
            try
            {
                var fs = new SHFILEOPSTRUCT
                                        {
                                            wFunc = FileOperationType.FO_DELETE,
                                            pFrom = path + '\0' + '\0',
                                            fFlags = flags
                                        };
                SHFileOperation(ref fs);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public static bool DeleteCompletelySilent(string path)
        {
            return deleteFile(path,
                              FileOperationFlags.FOF_NOCONFIRMATION | FileOperationFlags.FOF_NOERRORUI |
                              FileOperationFlags.FOF_SILENT);
        }
    }

【讨论】:

  • 如果为 64 位平台编译删除 Pack = 1(否则会失败)。如果没有指定 Pack = 1,这将适用于 32 位和 64 位。 pinvoke.net/default.aspx/Structures/SHFILEOPSTRUCT.html
  • 使用 Pack = 1 时,会引发 AccessViolationException。删除它就可以了。顺便说一下 64 位 Windows
  • 运行这段代码有什么要求?我删除了 Pack = 1 但它仍然无法编译。 DllImport、DllImportAttribute、MarshalAs、MarshalAsAttribute、StructLayout、StructLayoutAttribute 不作为命名空间存在。任何帮助请感谢:)
  • 注意:这对非 UI 交互应用程序(如 Windows 服务)不起作用,仅适用于 UI 交互应用程序
  • SHFileOperation 不处理长路径,如果路径长于 MAX_PATH(即使带有 \\?\ 前缀),也会失败。
【解决方案3】:

来自MSDN

添加对 Microsoft.VisualBasic 程序集的引用。在这个库中可以找到所需的类。

将此 using 语句添加到文件顶部 using Microsoft.VisualBasic.FileIO;

使用FileSystem.DeleteFile删除文件,可以选择是否指定回收站。

使用FileSystem.DeleteDirectory 删除目录,并可选择指定是否将其发送到回收站。

【讨论】:

  • 包含 Microsoct.VisualBasic 的问题在于它与我在程序其他地方(GetFiles() 函数的一部分)中使用 SearchOption 冲突。
  • @rar Downvote 仍然不值得,因为它没有在“由于冲突而无法引用 VisualBasic 库”的问题中指定。您可以在代码中轻松解决。 stackoverflow.com/questions/1317263/…
  • 此方法似乎在内部使用了 SHFileOperation,它不处理长路径,并且路径长于 MAX_PATH(即使带有 \\?\ 前缀)也会失败。
【解决方案4】:

以下解决方案比其他解决方案更简单:

using Shell32;

static class Program
{
    public static Shell shell = new Shell();
    public static Folder RecyclingBin = shell.NameSpace(10);

    static void Main()
    {
        RecyclingBin.MoveHere("PATH TO FILE/FOLDER")
    }
}

您可以使用此库使用回收站的其他功能。

首先,不要忘记添加库“Microsoft Shell Controls And Automation”(来自 COM 菜单),以便能够使用 Shell32 命名空间。它将动态链接到您的项目,而不是与您的程序一起编译。

【讨论】:

  • 当您专注于您的解决方案而不是在第一段中评论其他答案时,您的答案会更好。另外,为了清楚起见,我会将10 替换为Shell32.ShellSpecialFolderConstants.ssfBITBUCKET。可能值得一提的是 MoveHere 的第二个参数,关于 64 之类的选项(“如果可能,保留撤消信息”)。从 MSDN 链接一些文档源将是一个很好的整理。
  • 看起来对 MoveHere 的调用没有出现任何错误:在不存在的文件上调用它会静默失败!它也会在超过 MAX_CHARS 的路径上静默失败,无论是否带有“\\?\”前缀...
  • 它对我不起作用。它什么也不做,文件也没有被删除。
【解决方案5】:

不幸的是,您需要借助 Win32 API 将文件删除到回收站。尝试以下代码,基于this post。它利用通用SHFileOperation 函数通过Windows Shell 进行文件系统操作。

定义以下内容(在实用程序类中可能是最好的)。

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto, Pack=1)]
public struct SHFILEOPSTRUCT
{
        public IntPtr hwnd;
        [MarshalAs(UnmanagedType.U4)] public int wFunc;
        public string pFrom;
        public string pTo;
        public short fFlags;
        [MarshalAs(UnmanagedType.Bool)] public bool fAnyOperationsAborted;
        public IntPtr hNameMappings;
        public string lpszProgressTitle;
}

[DllImport("shell32.dll", CharSet=CharSet.Auto)]
public static extern int SHFileOperation(ref SHFILEOPSTRUCT FileOp);

public const int FO_DELETE = 3;
public const int FOF_ALLOWUNDO = 0x40;
public const int FOF_NOCONFIRMATION = 0x10; // Don't prompt the user

要使用它来删除文件,将其发送到回收站,您需要以下内容:

var shf = new SHFILEOPSTRUCT();
shf.wFunc = FO_DELETE;
shf.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION;
shf.pFrom = @"C:\test.txt";
SHFileOperation(ref shf);

【讨论】:

  • 和双空终止字符串。
  • SHFileOperation 不处理长路径,如果路径长于 MAX_PATH(即使带有 \\?\ 前缀),也会失败。
  • 请注意,shf.pFrom = @"C:\test.txt"; 这一行是错误的 - pFrom 必须以双空结尾。您应该在文件shf.pFrom = "C:\\text.txt\0"; 中添加\0。见docs.microsoft.com/en-us/windows/desktop/api/shellapi/…
【解决方案6】:

您可以通过 DllImport SHFileOperation 来执行此操作。

【讨论】:

  • SHFileOperation 不处理长路径,如果路径长于 MAX_PATH(即使带有 \\?\ 前缀),也会失败。
【解决方案7】:

为此有内置库

首先添加参考Microsoft.VisualBasic 然后添加此代码:

FileSystem.DeleteFile(path_of_the_file,
                        Microsoft.VisualBasic.FileIO.UIOption.AllDialogs,
                        Microsoft.VisualBasic.FileIO.RecycleOption.SendToRecycleBin,
                        Microsoft.VisualBasic.FileIO.UICancelOption.ThrowException);

我找到了这个here

【讨论】:

    【解决方案8】:

    我使用这种扩展方法,然后我可以只使用 DirectoryInfo 或 FileInfo 并删除它。

    public static class NativeMethods
    {
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            struct SHFILEOPSTRUCT
        {
            public IntPtr hwnd;
            [MarshalAs(UnmanagedType.U4)]
            public int wFunc;
            public string pFrom;
            public string pTo;
            public short fFlags;
            [MarshalAs(UnmanagedType.Bool)]
            public bool fAnyOperationsAborted;
            public IntPtr hNameMappings;
            public string lpszProgressTitle;
        }
        private const int FO_DELETE = 0x0003;
        private const int FOF_ALLOWUNDO = 0x0040;           // Preserve undo information, if possible. 
        private const int FOF_NOCONFIRMATION = 0x0010;      // Show no confirmation dialog box to the user      
    
    
        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        static extern int SHFileOperation(ref SHFILEOPSTRUCT FileOp);
    
        static bool DeleteFileOrFolder(string path)
        {
    
    
            SHFILEOPSTRUCT fileop = new SHFILEOPSTRUCT();
            fileop.wFunc = FO_DELETE;
            fileop.pFrom = path + '\0' + '\0';            
            fileop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION;
    
    
            var rc= SHFileOperation(ref fileop);
            return rc==0;
        }
    
        public static bool ToRecycleBin(this DirectoryInfo dir)
        {
            dir?.Refresh();
            if(dir is null || !dir.Exists)
            {
                return false;
            }
            else
                return DeleteFileOrFolder(dir.FullName);
        }
        public static bool ToRecycleBin(this FileInfo file)
        {
            file?.Refresh();
    
            if(file is null ||!file.Exists)
            {
                return false;
            }
            return DeleteFileOrFolder(file.FullName);
        }
    }
    

    如何调用它的示例可能是这样的:

    private void BtnDelete_Click(object sender, EventArgs e)
    {
        if(MessageBox.Show("Are you sure you would like to delete this directory?", "Delete & Close", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
            return;
    
        var dir= new DirectoryInfo(directoryName);
        dir.ToRecycleBin();
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-03
      • 2010-11-18
      • 2017-10-22
      相关资源
      最近更新 更多