Deleting file to recycle bin on Windows x64 in C#
I've got this class which seems to work quite well on non-64bit.
using System;
using System.Runtime.InteropServices;
namespace DeleteToRecycleBin
{
/// <summary>
/// Send files directly to the recycle bin.
/// </summary>
public class RecybleBin
{
/// <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, 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 readonly bool fAnyOperationsAborted;
public readonly IntPtr hNameMappings;
public readonly 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
{
SHFILEOPSTRUCT fs = new SHFILEOPSTRUCT
{
wFunc = FileOperationType.FO_DELETE,
pFrom = path + '\0' + '\0',
fFlags = FileOperationFlags.FOF_ALLOWUNDO | flags
};
// important to double-terminate the string.
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 SendSilent(string path)
{
return Send(path, FileOperationFlags.FOF_NOCONFIRMATION | FileOperationFlags.FOF_NOERRORUI | FileOperationFlags.FOF_SILENT);
}
}
}
Any way to fix it so it works good on x64 too? I've tried chaning ushort to ulong and couple of other modifications but it doesn't work.
I know there are other solutions that require reference to Microsoft.VisualBasic but i would prefer p/invoke way.
CORRECT ANSWER IS:
Under x64, the SHFILEOPSTRUCT must be declared without the Pack = 1 parameter, or it will fail. This is a real pain开发者_开发技巧 if you want your code to be platform independent, as you have to declare two separate structures, one with Pack = 1, and one without. You then have to declare two different SHFileOperation calls, one for each of the structures. Then you have to decide which one to call depending on whether you are running on 32 or 64 bit.
As strange as it seems, .NET already has functions to delete to the Recycle Bin... but they're in the Microsoft.VisualBasic
namespace. Specifically, Microsoft.VisualBasic.FileIO
.
using Microsoft.VisualBasic.FileIO;
// class declaration, method start here
// Send file to recycle bin without dialog
FileSystem.DeleteFile("pathToFile", UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
// Send file to recycle bin without dialog
FileSystem.DeleteFile("pathToFile", UIOption.AllDialogs, RecycleOption.SendToRecycleBin);
// Directories are the same, but with DeleteDirectory instead
Have you looked at the PInvoke site? It has a slight different definition for the FILEOPSTRUCT type, forcing Unicode for one thing. I wonder if the charset = auto is confusing things...like it defaults to ANSI on 32 bit, but Unicode on 64 bit and something is going wrong somewhere in the middle.
EDIT; Also, the Visual Basic reference approach is a simple one...I know people have an aversion to it for some reason, but the relevant DLLs are still part of the core framework, so you won't be adding any new dependencies.
精彩评论