Отправить файл в корзину

В настоящее время я использую следующую функцию

file.Delete();

Но как я могу использовать эту функцию для отправки файла в корзину вместо того, чтобы просто удалить его сразу?


person muttley91    schedule 19.07.2010    source источник
comment
msdn.microsoft.com/en-us/library/ms127976.aspx   -  person Jaroslav Jandek    schedule 19.07.2010
comment
Ссылка @UweKeim больше не работает, вы можете найти версию журнала MSDN Magazine в формате .chm (декабрь 2007 г.) здесь , статья называется .NET Matters: IFileOperation in Windows Vista и находится в папке Columns.   -  person jrh    schedule 04.10.2016
comment
У меня статья не открывается в .chm файле. Эта ссылка работает: docs.microsoft.com/en-us/archive/msdn-magazine/2007/декабрь/   -  person RandomEngy    schedule 03.07.2020
comment
Также вам нужно добавить FOFX_RECYCLEONDELETE = 0x00080000 к флагам операции, и этот флаг поддерживается только в Windows 8 или выше.   -  person RandomEngy    schedule 03.07.2020


Ответы (8)


ПРИМЕЧАНИЕ. Это также не работает с интерактивными приложениями без пользовательского интерфейса, такими как службы Windows.

Эта оболочка может предоставить вам необходимую функциональность:

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);
        }
    }
person Eugene Cheverda    schedule 19.07.2010
comment
Я не понимаю, как это использовать... не могли бы вы объяснить? - person muttley91; 19.07.2010
comment
Вы можете использовать его как статические методы для выполнения необходимых операций, использование настолько просто, насколько File.Delete(string filePath); - person Eugene Cheverda; 06.04.2011
comment
Удалите Pack = 1 при компиляции для 64-битной платформы (в противном случае произойдет сбой). Без указания Pack = 1 это будет работать как для 32-битной, так и для 64-битной версии. pinvoke.net/default.aspx/Structures/SHFILEOPSTRUCT.html - person Sean; 13.05.2013
comment
Этот код завершается тройным нулем. Вы добавили еще один нулевой терминатор, чем нужно. - person David Heffernan; 13.11.2013
comment
При использовании Pack = 1 возникало исключение AccessViolationException. Удаление сделало свое дело. 64-битная винда кстати - person P1nGu1n; 27.12.2013
comment
Каковы требования даже для запуска этого кода? Убираю Pack=1 но все равно не компилируется. DllImport, DllImportAttribute, MarshalAs, MarshalAsAttribute, StructLayout, StructLayoutAttribute не существуют как пространство имен. Любая помощь, пожалуйста, спасибо :) - person puretppc; 25.01.2014
comment
@puretppc using System.Runtime.InteropServices; - person Dan Is Fiddling By Firelight; 15.09.2014
comment
ПРИМЕЧАНИЕ. Это не работает с интерактивными приложениями без пользовательского интерфейса, такими как службы Windows, только с интерактивными приложениями с пользовательским интерфейсом. - person rboy; 28.05.2015
comment
Я думаю, что оба подхода (FileSystem.DeleteFile и P/Invoke to SHFileOperation) имеют свою причину для существования, и в зависимости от вашего приоритета один из них подходит именно вам. Лично для меня намного удобнее использовать хорошо известный системный API вместо другого фреймворка, который охватывает базовое использование ОС, для других более важной может быть совместимость. Проголосовал за, потому что код очень ясен и действительно отвечает на вопрос. - person Xan-Kun Clark-Davis; 16.02.2017
comment
Есть ли причина, по которой класс не является статическим? - person Xan-Kun Clark-Davis; 16.02.2017
comment
SHFileOperation не обрабатывает длинные пути и не работает с путями длиннее MAX_PATH (даже с префиксом \\?\). - person Melvyn; 12.03.2018

Используйте FileSystem.DeleteFile и укажите справа RecycleOption.

Хотя это будет работать с интерактивными приложениями пользовательского интерфейса, оно не будет работать с интерактивными приложениями без пользовательского интерфейса, такими как приложение службы Windows.

person NG.    schedule 19.07.2010
comment
Работает, но не идеально. Ссылка на Microsoft.VisualBasic часто нежелательна из C#. Любая ассоциация с VB из кода C# кажется мне уродливой. (Хотя это не мой отрицательный голос.) - person Noldorin; 19.07.2010
comment
@noldorin Это прекрасное решение, не заслуживающее отрицательного голоса. Мне нужна ссылка на то, почему доступ к библиотеке VisualBasic уродлив. - person jsmith; 19.07.2010
comment
@noldorin: Особенно в этом случае Microsoft.VisualBasic.FileIO.FileSystem делает в основном то же самое, что и пример, опубликованный здесь, с использованием SHFileOperation. - person Dirk Vollmar; 19.07.2010
comment
@Noldorin: Некрасиво, да? Для меня способ WinAPI намного уродливее - кроме того, у вас больше шансов что-то испортить. Мне лично не нравится синтаксис VB, но в сборках он просто IL, так что я не против. Кстати, сборка VB вызывает ту же функцию WinAPI. - person Jaroslav Jandek; 19.07.2010
comment
Я не голосовал против. Это не уродливо само по себе, его просто не следует использовать из С#. Насколько я понимаю, он довольно устарел. - person Noldorin; 19.07.2010
comment
@Noldorin: устарело? Вы случайно не перепутали сборку с Microsoft.VisualBasic.Compatibility? Этого я избегал. Не похоже, что в ближайшее время он станет устаревшим (он используется в механизме отчетов RDL и т. д.). - person Jaroslav Jandek; 19.07.2010
comment
@Noldorin: использование встроенной сборки фреймворка выглядит лучшим решением, чем жесткое сопоставление с shell32.dll. Используя сборки фреймворка, вы получаете переносимое изменение и более поздние модификации. Сопоставляя системные библиотеки, вы рискуете устаревать в любой день... - person fredlegrain; 08.04.2013
comment
@fredlegrain: Но мы знаем, что Microsoft.VisualBasic.FileIO в любом случае просто использует переходники shell32 под капотом. ;) - person Noldorin; 08.04.2013
comment
@Noldorin: Верно, так зачем переписывать что-то, что уже упаковано где-то во фреймворке? - person fredlegrain; 12.04.2013
comment
Потому что он привязан к системе Visual Basic, конечно. Он даже не предназначен для использования в C# и действительно может исчезнуть в любой момент в будущем, в то время как собственно C# останется полностью. - person Noldorin; 14.04.2013
comment
@Noldorin, независимо от того, на каком языке программирования .NET вы знаете, что он будет на одном и том же скомпилированном языке, верно? - person EaterOfCode; 22.05.2013
comment
Однако вы не знаете, какие библиотеки DLL будут доступны в системе в будущем. Если что-то и нужно удалить, так это такую ​​DLL. Хотя MS одержимы обратной совместимостью, так что, возможно, ни один из них никогда не будет удален. Yay для раздувания? - person Noldorin; 22.05.2013
comment
Для меня это работает на локальном хосте, но при размещении на сервере Windows 2012 с IIS не работает. Файл удаляется, но не попадает в корзину. Нет ошибки. Любая проблема с разрешением? - person d-coder; 08.06.2014
comment
@singh на вашем сервере есть корзина. Я часто вижу, что на серверах отключена корзина. - person DonkeyMaster; 24.09.2014
comment
@DonkeyMaster: Да, он включен; Или как бы я проверил, не входит ли он туда. - person d-coder; 25.09.2014
comment
Хотя это работает в приложениях пользовательского пространства с интерфейсом пользовательского интерфейса, это НЕ будет работать с интерактивным приложением без пользовательского интерфейса, таким как служба Windows (я узнал это на собственном горьком опыте). Цитата из MSDN Параметры showUI и recycle не поддерживаются в приложениях, не взаимодействующих с пользователем, таких как службы Windows. - person rboy; 28.05.2015
comment
Это гораздо лучшее решение, чем принятый ответ. Я даже создал решение на F#, в котором используется этот подход, и оно отлично работает. Пока вы говорите ему компилироваться как приложение Windows, а не как консольное приложение, оно работает. - person Jacobs Data Solutions; 11.07.2015
comment
Этот метод, по-видимому, внутренне использует SHFileOperation, который не обрабатывает длинные пути и не работает с путями, длина которых превышает MAX_PATH (даже с префиксом \\?\). - person Melvyn; 12.03.2018
comment
Ему также не нравится быть вне потока пользовательского интерфейса в вызове Async. - person CAD bloke; 09.02.2020

Из MSDN :

Добавьте ссылку на сборку Microsoft.VisualBasic. В этой библиотеке находится нужный класс.

Добавьте этот оператор using в начало файла using Microsoft.VisualBasic.FileIO;

Используйте FileSystem.DeleteFile для удаления файла, у него есть возможность указать корзину или нет.

Используйте FileSystem.DeleteDirectory для удаления каталога с возможностью указать, отправлять его в корзину или нет.

person John Warlow    schedule 19.07.2010
comment
Проблема с включением Microsoct.VisualBasic заключается в том, что это конфликтует с моим использованием SearchOption в другом месте моей программы (часть функции GetFiles()). - person muttley91; 19.07.2010
comment
@rar Downvote по-прежнему не заслуживает, поскольку в вопросе не было указано, что на библиотеку VisualBasic нельзя ссылаться из-за конфликта. Что вы могли бы легко решить в своем коде. stackoverflow.com/questions/1317263/ - person jsmith; 19.07.2010
comment
Этот метод, по-видимому, внутренне использует SHFileOperation, который не обрабатывает длинные пути и не работает с путями, длина которых превышает MAX_PATH (даже с префиксом \\?\). - person Melvyn; 12.03.2018

Следующее решение проще, чем другие:

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. Он будет динамически связан с вашим проектом, а не компилируется вместе с вашей программой.

[1]: https://i.stack.imgur.com/erV

person Community    schedule 08.05.2017
comment
Ваш ответ будет лучше, если вы сосредоточитесь на своем решении, а не комментируете другие ответы в первом абзаце. Кроме того, для ясности я бы заменил 10 на Shell32.ShellSpecialFolderConstants.ssfBITBUCKET. Возможно, стоит упомянуть второй параметр MoveHere относительно таких параметров, как 64 (сохранять информацию об отмене, если это возможно). Ссылка на некоторые источники документации из MSDN была бы хорошим завершением. - person grek40; 15.05.2017
comment
Похоже, что вызов MoveHere не вызывает никаких ошибок: вызов его для несуществующего файла завершается с ошибкой! Он также молча терпит неудачу на путях длиннее MAX_CHARS, с префиксом \\?\ или без него... - person Melvyn; 12.03.2018
comment
Это не работает для меня. Он просто ничего не делает и файл не удаляется. - person Elmue; 21.05.2021

К сожалению, вам нужно прибегнуть к Win32 API, чтобы удалить файл в корзину. Попробуйте использовать следующий код на основе этот пост. Он использует общую функцию SHFileOperation для операций с файловой системой через оболочку Windows.

Определите следующее (вероятно, лучше всего в классе утилит).

[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);
person Noldorin    schedule 19.07.2010
comment
и двойной нуль завершает строку. - person sean e; 15.04.2013
comment
SHFileOperation не обрабатывает длинные пути и не работает с путями длиннее MAX_PATH (даже с префиксом \\?\). - person Melvyn; 12.03.2018
comment
Обратите внимание, что эта строка shf.pFrom = @"C:\test.txt"; неверна - pFrom должен заканчиваться двойным нулем. Вы должны добавить \0 в файл shf.pFrom = "C:\\text.txt\0";. См. docs.microsoft.com/en-us. /windows/рабочий стол/api/shellapi/ - person lindexi; 22.03.2019

Для этого существует встроенная библиотека.

Сначала добавьте ссылку Microsoft.VisualBasic. Затем добавьте этот код:

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

Я нашел этот здесь .

person Maifee Ul Asad    schedule 19.01.2019

Для этого можно использовать DllImport SHFileOperation.

person Brian R. Bondy    schedule 19.07.2010
comment
SHFileOperation не обрабатывает длинные пути и не работает с путями длиннее MAX_PATH (даже с префиксом \\?\). - person Melvyn; 12.03.2018

Я использую этот метод расширения, тогда я могу просто использовать 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();

}
person Walter Vehoeven    schedule 04.10.2019