휴지통으로 파일 보내기


83

현재 다음 기능을 사용하고 있습니다

file.Delete();

하지만이 기능을 사용하여 파일을 완전히 삭제하는 대신 휴지통으로 보내려면 어떻게해야합니까?



3
@UweKeim의 링크는 이제 죽었습니다. MSDN Magazine (2007 년 12 월)의 .chm 형식 버전을 여기.NET Matters: IFileOperation in Windows Vista 에서 찾을 수 Columns있습니다. 기사가 호출 되고 폴더 에서 찾을 수 있습니다.
jrh

.chm 파일에서 문서가 열리지 않습니다. 이 링크는 작동합니다. docs.microsoft.com/en-us/archive/msdn-magazine/2007/december/…
RandomEngy

또한 FOFX_RECYCLEONDELETE = 0x00080000작업 플래그 에 추가해야 하며 해당 플래그는 Windows 8 이상에서만 지원됩니다.
RandomEngy

답변:


52

참고 : 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);
        }
    }

어떻게 사용하는지 모르겠네요 ... 설명해 주 시겠어요?
muttley91 2010-07-19

4
64 비트 플랫폼 용으로 컴파일하는 경우 Pack = 1을 제거합니다 (그렇지 않으면 실패합니다). Pack = 1을 지정하지 않으면 32 비트와 64 비트 모두에서 작동합니다. pinvoke.net/default.aspx/Structures/SHFILEOPSTRUCT.html
Sean

1
Pack = 1을 사용할 때 AccessViolationException이 발생했습니다. 그것을 제거하면 트릭이되었습니다. 참고로 64 비트 Windows
P1nGu1n

1
이 코드를 실행하기위한 요구 사항은 무엇입니까? Pack = 1을 제거했지만 여전히 컴파일되지 않습니다. DllImport, DllImportAttribute, MarshalAs, MarshalAsAttribute, StructLayout, StructLayoutAttribute는 네임 스페이스로 존재하지 않습니다. 어떤 도움 감사합니다 :) 제발
puretppc

1
SHFileOperation은 긴 경로를 처리하지 않으며 MAX_PATH보다 긴 경로 (\\? \ 접두어 포함)에서는 실패합니다.
Melvyn

155

사용 FileSystem.DeleteFile 과 오른쪽 지정 RecycleOption을 .

이것은 UI 대화 형 앱에서 작동하지만 Windows 서비스 앱과 같은 비 UI 대화 형 앱에서는 작동하지 않습니다.


17
@noldorin 이것은 완벽하게 훌륭한 솔루션이며 반대표를받을 자격이 없습니다. VisualBasic 라이브러리에 액세스하는 것이 "추악"한 이유에 대한 참조를 원합니다.
jsmith

7
@noldorin : 특히이 경우 Microsoft.VisualBasic.FileIO.FileSystem여기에 게시 된 예제와 기본적으로 SHFileOperation.
Dirk Vollmar

18
@Noldorin : 못생긴, 응? 나에게 WinAPI 방식은 훨씬 더 추악합니다. 또한 무언가를 엉망으로 만드는 것이 더 좋습니다. 저는 개인적으로 VB 구문을 싫어 하지만 어셈블리에서는 괜찮습니다 IL. VB 어셈블리는 동일한 WinAPI 함수 btw를 호출합니다.
Jaroslav Jandek

7
@Noldorin : 구식? Microsoft.VisualBasic.Compatibility우연히 어셈블리를 착각 했습니까 ? 내가 그 일 것입니다 마십시오. 조만간 더 이상 사용되지 않을 것 같지는 않습니다 (RDL보고 엔진 등에서 사용됨).
Jaroslav Jandek

6
@Noldorin : 내장 프레임 워크 어셈블리를 사용하는 것이 shell32.dll에 대한 하드 스타일 매핑보다 나은 솔루션처럼 보입니다. 프레임 워크 어셈블리를 사용하면 변경 사항을 이식 할 수 있고 나중에 진화 할 수 있습니다. 시스템 라이브러리에 매핑, 당신은 ... 어떤 일 무용지물이 될 모든 위험을 무릅
fredlegrain

41

에서 MSDN :

Microsoft.VisualBasic 어셈블리에 대한 참조를 추가합니다. 필요한 클래스는이 라이브러리에서 찾을 수 있습니다.

이 using 문을 파일 맨 위에 추가합니다 using Microsoft.VisualBasic.FileIO.

FileSystem.DeleteFile파일을 삭제하는 데 사용 하며 휴지통을 지정하거나 지정하지 않는 옵션이 있습니다.

사용 FileSystem.DeleteDirectory휴지통 여부에 보내도록 지정하는 옵션으로 디렉토리를 삭제합니다.


Microsoct.VisualBasic을 포함 할 때의 문제는 내 프로그램의 다른 곳에서 SearchOption을 사용하는 것과 충돌한다는 것입니다 (GetFiles () 함수의 일부).
muttley91

8
@rar Downvote는 "충돌로 인해 VisualBasic 라이브러리를 참조 할 수 없습니다."라는 질문에 지정되지 않았기 때문에 여전히 자격이 없습니다. 코드에서 쉽게 해결할 수 있습니다. stackoverflow.com/questions/1317263/…
jsmith

1
이 메서드는 내부적으로 SHFileOperation을 사용하는 것으로 보이며, 긴 경로를 처리하지 않으며 MAX_PATH보다 긴 경로 (\\? \ 접두어 포함)에서는 실패합니다.
Melvyn

17

다음 솔루션은 다른 솔루션보다 간단합니다.

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")
    }
}

이 라이브러리를 사용하여 휴지통의 다른 기능을 사용할 수 있습니다.

첫째, Shell32네임 스페이스 를 사용할 수 있도록 COM 메뉴에서 "Microsoft Shell Controls And Automation"라이브러리를 추가하는 것을 잊지 마십시오 . 프로그램과 함께 컴파일되는 대신 프로젝트에 동적으로 연결됩니다.

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


8
첫 번째 단락에서 다른 답변을 설명하는 대신 솔루션에 집중할 때 답변이 더 나을 것입니다. 또한, 명확성을 위해 나는 대체 것 10으로 Shell32.ShellSpecialFolderConstants.ssfBITBUCKET. MoveHere64 ( "가능한 경우 실행 취소 정보 유지")와 같은 옵션과 관련 하여 에 대한 두 번째 매개 변수를 언급 할 가치가 있습니다 . MSDN의 일부 문서 소스를 연결하면 멋진 마무리가 될 것입니다.
grek40

2
MoveHere를 호출해도 오류가 표시되지 않는 것 같습니다. 존재하지 않는 파일에서 호출하면 자동으로 실패합니다! 또한 ...로 또는 "\\? \"접두사없이, 더 MAX_CHARS 이상의 경로에 자동으로 실패
Melvyn

13

불행히도 Win32 API를 사용하여 휴지통에있는 파일을 제거해야합니다. 이 게시물을 기반으로 다음 코드를 시도하십시오 . SHFileOperationWindows 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);

1
이중 null은 문자열을 종료합니다.
sean e

1
SHFileOperation은 긴 경로를 처리하지 않으며 MAX_PATH보다 긴 경로 (\\? \ 접두어 포함)에서는 실패합니다.
Melvyn

이 줄 shf.pFrom = @"C:\test.txt";이 잘못되었습니다. pFrom은 null로 끝나는 이중 null이어야합니다. \0파일에 추가해야 합니다 shf.pFrom = "C:\\text.txt\0";. docs.microsoft.com/en-us/windows/desktop/api/shellapi/…
lindexi


1

이 확장 방법을 사용하면 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();

}

-1

이에 대한 내장 라이브러리 가 있습니다.

먼저 참조 Microsoft.VisualBasic을 추가 한 다음 다음 코드를 추가합니다.

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

나는 여기 에서 이것을 발견 했다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.