tags:

views:

232

answers:

5

Currently I'm using the following function

file.Delete();

But how can I use this function to send a file to the recycle bin instead of just deleting it outright?

+1  A: 

You can DllImport SHFileOperation to do this.

Brian R. Bondy
+7  A: 

Use FileSystem.DeleteFile and specify the right RecycleOption.

SB
Works, but not ideal. Referencing the Microsoft.VisualBasic is often undesirable from within C#. Any association with VB from within C# code strikes me as ugly. (Not my down-vote though.)
Noldorin
@noldorin This is a perfectly fine solution, doesn't deserve a downvote. I'd like a reference on why accessing the VisualBasic library is "ugly".
jsmith
@noldorin: Especially in this case `Microsoft.VisualBasic.FileIO.FileSystem` does basically the same as the example posted here using `SHFileOperation`.
0xA3
@Noldorin: Ugly, huh? For me the WinAPI way is way uglier - also, you have better shot at messing something up. I personally dislike VB **syntax** but in assemblies it's just `IL` so I don't mind. The VB assembly calls the same WinAPI function btw.
Jaroslav Jandek
I did not down-vote. It's not ugly per se, it just shouldn't be used from within C#. It is pretty much obsolete as far as I'm concerned.
Noldorin
@Noldorin: Obsolete? Have you mistaken the assembly for `Microsoft.VisualBasic.Compatibility` by chance? That one I **would** avoid. Doesn't seem like it's going to be deprecated any time soon (it's used in the RDL reporting engine, etc.).
Jaroslav Jandek
+5  A: 

Unfortunately you need to resort to the Win32 API to remove a file to the Recycle Bin. Try the following code, based on this post. It makes use of the generic SHFileOperation function for file system operations via the Windows Shell.

Define the following (in a utilities class is probably best).

[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

And to use it to delete a file, sending it to the Recycle Bin, you want something like:

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

From MSDN:

Add a reference to Microsoft.VisualBasic assembly. The needed class is found in this library.

Add this using statement to the top of the file using Microsoft.VisualBasic.FileIO;

Use FileSystem.DeleteFile to delete a file, it has the option to specify recycle bin or not.

Use FileSystem.DeleteDirectory to delete a directory with the option to specify to send it to the recycle bin or not.

JLWarlow
The downvoter owes a comment. This solution works just fine for simply sending a file to the recycle bin.
jsmith
The problem with including Microsoct.VisualBasic is that it conflicts with my use of SearchOption elsewhere in my program (part of the GetFiles() function).
rar
@rar Downvote is still not deserved since it was not specified in the question that "VisualBasic library cannot be referenced due to conflict." Which you could easily resolve in your code. http://stackoverflow.com/questions/1317263/system-io-versus-visualbasic-fileio
jsmith
oh i know, I didn't downvote either. I was only responding as I'd found it out later.
rar
I don't see how I can fix that problem though :S
rar
+3  A: 

This wrapper can provide you needed functionality:

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

        /// <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);
        }
    }
Eugene Cheverda
I don't understand how to use this...could you explain?
rar