0

在此处输入图像描述

如何通过C#或windows api删除多项,我已经搜索了很长时间,没有解决方案。我在Shell32.dll中使用FolderItemVerb一个一个地删除文件,但它会同时弹出一个对话框。如果您知道如何解决此问题,我将不胜感激。谢谢你。

4

2 回答 2

1

这不适合胆小的人!

代码兼容 Windows >= Vista,没有 XP!XP代码在最后

这是我第一次看Shell32接口...哇...即使是最简单的东西也很复杂:-) 但是COM总是很复杂...现在...有2.5种竞争数据结构/interfaces 用于在 Shell 中操作文件... IShellFolder(旧 COM 接口,本示例中未使用),IShellItem(新 COM 接口,本示例中使用),IDLIST(此处用作 a PIDLIST_ABSOLUTE,用于将多个文件“收集”在一起。我把它算作 0.5 )。我希望任何地方都没有内存泄漏(总是很复杂)。请注意,.NET 将自动释放 COM 对象。我什至添加了一些我编写的代码来帮助我调试(比如获取支持的动词列表的代码)。

现在,这里有 COM 接口以及一些Shell32.dll PInvoke 方法。

[StructLayout(LayoutKind.Sequential)]
public struct PIDLIST_ABSOLUTE
{
    public IntPtr Ptr;
}

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")]
public interface IShellItem
{
    void BindToHandler(
        IntPtr pbc,
        [In, MarshalAs(UnmanagedType.LPStruct)] Guid bhid,
        [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
        [MarshalAs(UnmanagedType.IUnknown)] out object ppv);

    void GetParent(out IShellItem ppsi);

    void GetDisplayName(int sigdnName, out IntPtr ppszName);

    void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs);

    [PreserveSig]
    int Compare(IShellItem psi, uint hint, out int piOrder);
}

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("70629033-e363-4a28-a567-0db78006e6d7")]
public interface IEnumShellItems
{
    void Next(int celt, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] IShellItem[] rgelt, out int pceltFetched);

    void Skip(int celt);

    void Reset();

    void Clone(out IEnumShellItems ppenum);
}

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("b63ea76d-1f85-456f-a19c-48159efa858b")]
public interface IShellItemArray
{
    void BindToHandler(
        IntPtr pbc,
        [In, MarshalAs(UnmanagedType.LPStruct)] Guid bhid,
        [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
        [MarshalAs(UnmanagedType.IUnknown)] out object ppvOut);

    void GetPropertyStore(
        uint flags,
        [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
        [MarshalAs(UnmanagedType.IUnknown)] out object ppv);

    void GetPropertyDescriptionList(
        IntPtr keyType,
        [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
        [MarshalAs(UnmanagedType.IUnknown)] out object ppv);

    void GetAttributes(uint AttribFlags, uint sfgaoMask, out uint psfgaoAttribs);

    void GetCount(out int pdwNumItems);

    void GetItemAt(int dwIndex, out IShellItem ppsi);

    void EnumItems(out IEnumShellItems ppenumShellItems);
}

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("000214e4-0000-0000-c000-000000000046")]
public interface IContextMenu
{
    [PreserveSig]
    int QueryContextMenu(IntPtr hMenu, uint indexMenu, int idCmdFirst, int idCmdLast, uint uFlags);

    void InvokeCommand([In] ref CMINVOKECOMMANDINFOEX pici);

    [PreserveSig]
    int GetCommandString(UIntPtr idCmd, uint uType, IntPtr pReserved, IntPtr pszName, int cchMax);
}

[StructLayout(LayoutKind.Sequential)]
public struct CMINVOKECOMMANDINFOEX
{
    public int cbSize;
    public uint fMask;
    public IntPtr hwnd;

    // Non-unicode verbs (are there unicode verbs?)
    [MarshalAs(UnmanagedType.LPStr)]
    public string lpVerb;

    [MarshalAs(UnmanagedType.LPStr)]
    public string lpParameters;

    [MarshalAs(UnmanagedType.LPStr)]
    public string lpDirectory;

    public int nShow;
    public uint dwHotKey;
    public IntPtr hIcon;

    [MarshalAs(UnmanagedType.LPStr)]
    public string lpTitle;

    // Use CMIC_MASK_UNICODE
    [MarshalAs(UnmanagedType.LPWStr)]
    public string lpVerbW;

    [MarshalAs(UnmanagedType.LPWStr)]
    public string lpParametersW;

    [MarshalAs(UnmanagedType.LPWStr)]
    public string lpDirectoryW;

    [MarshalAs(UnmanagedType.LPWStr)]
    public string lpTitleW;

    public int ptInvokeX;
    public int ptInvokeY;
}

// Windows >= Vista
public static class ShellItemUtilities
{
    public static readonly Guid FOLDERID_RecycleBinFolder = new Guid("b7534046-3ecb-4c18-be4e-64cd4cb7d6ac");

    public static readonly Guid BHID_EnumItems = new Guid("94f60519-2850-4924-aa5a-d15e84868039");

    public static readonly Guid BHID_SFUIObject = new Guid("3981e225-f559-11d3-8e3a-00c04f6837d5");

    // From Windows 7
    [DllImport("Shell32.dll", ExactSpelling = true, SetLastError = false)]
    public static extern int SHGetKnownFolderItem(
        [In, MarshalAs(UnmanagedType.LPStruct)] Guid rfid,
        uint dwFlags,
        IntPtr hToken,
        [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
        out IShellItem ppv);

    // For Windows Vista
    [DllImport("Shell32.dll", ExactSpelling = true, SetLastError = false)]
    public static extern int SHCreateItemFromIDList(PIDLIST_ABSOLUTE pidl, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IShellItem ppv);

    // For Windows Vista
    [DllImport("Shell32.dll", ExactSpelling = true, SetLastError = false)]
    public static extern int SHGetKnownFolderIDList(
        [In, MarshalAs(UnmanagedType.LPStruct)] Guid rfid,
        uint dwFlags,
        IntPtr hToken,
        out PIDLIST_ABSOLUTE ppidl);

    // From Windows Vista
    [DllImport("Shell32.dll", ExactSpelling = true, SetLastError = false)]
    public static extern int SHGetIDListFromObject([MarshalAs(UnmanagedType.Interface)] object punk, out PIDLIST_ABSOLUTE ppidl);

    [DllImport("Shell32.dll", ExactSpelling = true, SetLastError = false)]
    public static extern int SHCreateShellItemArrayFromIDLists(int cidl, [In] PIDLIST_ABSOLUTE[] rgpidl, out IShellItemArray ppsiItemArray);

    public static IEnumerable<IShellItem> Enumerate(this IShellItem si)
    {
        object pesiTemp;
        si.BindToHandler(IntPtr.Zero, BHID_EnumItems, typeof(IEnumShellItems).GUID, out pesiTemp);
        var pesi = (IEnumShellItems)pesiTemp;

        var items = new IShellItem[10];

        while (true)
        {
            int fetched;

            pesi.Next(1, items, out fetched);

            if (fetched == 0)
            {
                break;
            }

            yield return items[0];
        }
    }
}

public static class ContextMenuUtilities
{
    [DllImport("User32.dll", ExactSpelling = true, SetLastError = true)]
    public static extern IntPtr CreateMenu();

    [DllImport("User32.dll", ExactSpelling = true, SetLastError = true)]
    public static extern bool DestroyMenu(IntPtr hMenu);

    [DllImport("User32.dll", ExactSpelling = true, SetLastError = true)]
    public static extern int GetMenuItemCount(IntPtr hMenu);

    [DllImport("User32.dll", ExactSpelling = true, SetLastError = true)]
    public static extern uint GetMenuItemID(IntPtr hMenu, int nPos);

    [DllImport("User32.dll", CharSet = CharSet.Unicode, EntryPoint = "GetMenuStringW", ExactSpelling = true, SetLastError = true)]
    public static extern int GetMenuString(IntPtr hMenu, uint uIDItem, [Out] StringBuilder lpString, int nMaxCount, uint uFlag);

    public static string[] GetVerbs(IContextMenu cm, bool ansi = true)
    {
        IntPtr menu = IntPtr.Zero;

        try
        {
            menu = CreateMenu();

            // It isn't clear why short.MaxValue, but 0x7FFF is very used around the .NET!
            int res = cm.QueryContextMenu(menu, 0, 0, short.MaxValue, 0);

            if (res < 0)
            {
                Marshal.ThrowExceptionForHR(res);
            }

            //var sb = new StringBuilder(128);

            int count = GetMenuItemCount(menu);

            var verbs = new List<string>(count);

            var handle = default(GCHandle);

            try
            {
                var bytes = new byte[ansi ? 128 : 256];

                handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                IntPtr ptr = handle.AddrOfPinnedObject();

                for (int i = 0; i < count; i++)
                {
                    uint id = GetMenuItemID(menu, i);

                    if (id == uint.MaxValue)
                    {
                        continue;
                    }

                    //GetMenuString(menu, (uint)i, sb, sb.Capacity, 0x00000400 /* MF_BYPOSITION */);
                    //string description = sb.ToString();
                    //sb.Clear();

                    res = cm.GetCommandString((UIntPtr)id, ansi ? (uint)0x00000002 /* GCS_VALIDATEA */ : 0x00000006 /* GCS_VALIDATEW */, IntPtr.Zero, ptr, bytes.Length);

                    if (res < 0)
                    {
                        continue;
                    }

                    if (res == 0)
                    {
                        res = cm.GetCommandString((UIntPtr)id, ansi ? (uint)0x00000000 /* GCS_VERBA */ : 0x00000004 /* GCS_VERBW */, IntPtr.Zero, ptr, bytes.Length);

                        if (res < 0)
                        {
                            Marshal.ThrowExceptionForHR(res);
                        }

                        verbs.Add(ansi ? Marshal.PtrToStringAnsi(ptr) : Marshal.PtrToStringUni(ptr));
                    }
                }
            }
            finally
            {
                if (handle.IsAllocated)
                {
                    handle.Free();
                }
            }

            return verbs.ToArray();
        }
        finally
        {
            if (menu != IntPtr.Zero)
            {
                DestroyMenu(menu);
            }
        }
    }
}

最后是一个使用它的小示例程序......这是一个小型控制台方法,它将列出回收站中存在的所有文件,将其中的 10 个文件放入一个数组中,并在一次操作中删除它们(动词) . 这SHGetKnownFolderItem是从 Windows 7 开始的,所以我使用的是来自 Windows Vista 的SHGetKnownFolderIDList+ SHCreateItemFromIDList

此处的代码枚举IShellItem回收站中包含的文件,将它们保存PIDL_ABSOLUTE在 a 中List<>,从中List<>创建 a IShellItemArray,在其上IShellItemArray绑定 a IContextMenu,用于IContextMenu执行delete动词。显然,通过添加/不添加所有文件PIDL_ABSOLUTEList<>您可以控制哪些文件将被删除。

private static void TestShellItem()
{
    IShellItem recyleBin;
    string str;
    IntPtr ptr = IntPtr.Zero;
    int res;

    //// From Windows 7
    //res = ShellItemUtilities.SHGetKnownFolderItem(ShellItemUtilities.FOLDERID_RecycleBinFolder, 0, IntPtr.Zero, typeof(IShellItem).GUID, out recyleBin);

    //if (res < 0)
    //{
    //    Marshal.ThrowExceptionForHR(res);
    //}

    // Windows >= Vista equivalent
    var pidl = default(PIDLIST_ABSOLUTE);

    try
    {
        res = ShellItemUtilities.SHGetKnownFolderIDList(ShellItemUtilities.FOLDERID_RecycleBinFolder, 0, IntPtr.Zero, out pidl);

        if (res < 0)
        {
            Marshal.ThrowExceptionForHR(res);
        }

        res = ShellItemUtilities.SHCreateItemFromIDList(pidl, typeof(IShellItem).GUID, out recyleBin);

        if (res < 0)
        {
            Marshal.ThrowExceptionForHR(res);
        }
    }
    finally
    {
        Marshal.FreeCoTaskMem(pidl.Ptr);
    }

    //// Example of use of GetDisplayName
    //try
    //{
    //    recyleBin.GetDisplayName(2, out ptr);
    //    str = Marshal.PtrToStringUni(ptr);
    //}
    //finally
    //{
    //    if (ptr != IntPtr.Zero)
    //    {
    //        Marshal.FreeCoTaskMem(ptr);
    //        ptr = IntPtr.Zero;
    //    }
    //}

    var pids = new List<PIDLIST_ABSOLUTE>();

    try
    {
        foreach (IShellItem si in recyleBin.Enumerate())
        {
            try
            {
                si.GetDisplayName(0, out ptr);

                str = Marshal.PtrToStringUni(ptr);

                // Some condition to include/exclude...
                if (pids.Count < 10)
                {
                    Console.WriteLine(str);

                    // Remember to free the pidl!
                    res = ShellItemUtilities.SHGetIDListFromObject(si, out pidl);

                    if (res < 0)
                    {
                        Marshal.ThrowExceptionForHR(res);
                    }

                    pids.Add(pidl);
                }
            }
            finally
            {
                if (ptr != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(ptr);
                    ptr = IntPtr.Zero;
                }
            }
        }

        var pids2 = pids.ToArray();

        IShellItemArray sia;

        res = ShellItemUtilities.SHCreateShellItemArrayFromIDLists(pids2.Length, pids2, out sia);

        if (res < 0)
        {
            Marshal.ThrowExceptionForHR(res);
        }

        object cmTemp;
        sia.BindToHandler(IntPtr.Zero, ShellItemUtilities.BHID_SFUIObject, typeof(IContextMenu).GUID, out cmTemp);
        var cm = (IContextMenu)cmTemp;

        // To see verbs
        //var verbsAnsi = ContextMenuUtilities.GetVerbs(cm, true);
        //var verbsUnicode = ContextMenuUtilities.GetVerbs(cm, false);

        var cmd = new CMINVOKECOMMANDINFOEX
        {
            cbSize = Marshal.SizeOf(typeof(CMINVOKECOMMANDINFOEX)),
            fMask = 0x00000400 /* CMIC_MASK_FLAG_NO_UI */,
            lpVerb = "delete",
        };

        cm.InvokeCommand(ref cmd);
    }
    finally
    {
        foreach (var pid in pids)
        {
            Marshal.FreeCoTaskMem(pid.Ptr);
        }
    }

    //// Verb executed one by one
    //foreach (var item in recyleBin.Enumerate())
    //{
    //    object cmTemp;
    //    item.BindToHandler(IntPtr.Zero, ShellItemUtilities.BHID_SFUIObject, typeof(IContextMenu).GUID, out cmTemp);
    //    var cm = (IContextMenu)cmTemp;

    ////// To see verbs
    ////    var verbsAnsi = ContextMenuUtilities.GetVerbs(cm, true);
    ////    var verbsUnicode = ContextMenuUtilities.GetVerbs(cm, false);

    //    var cmd = new CMINVOKECOMMANDINFOEX
    //    {
    //        cbSize = Marshal.SizeOf(typeof(CMINVOKECOMMANDINFOEX)),
    //        fMask = 0x00000400 /* CMIC_MASK_FLAG_NO_UI */,
    //        lpVerb = "delete",
    //    };

    //    cm.InvokeCommand(ref cmd);
    //}
}

Windows XP 的代码,使用了其他版本的一些代码,你必须拿走你需要的东西

它使用IShellFolder接口。请注意,IContextMenu处理方式完全相同。

[StructLayout(LayoutKind.Sequential)]
public struct PIDLIST_RELATIVE
{
    public IntPtr Ptr;
}

[StructLayout(LayoutKind.Sequential)]
public struct LPITEMIDLIST
{
    public IntPtr Ptr;
}

[StructLayout(LayoutKind.Sequential)]
public struct PITEMID_CHILD
{
    public IntPtr Ptr;
}

public enum STRRET_TYPE
{
    WSTR = 0,
    OFFSET = 0x1,
    CSTR = 0x2
};

[StructLayout(LayoutKind.Sequential, Pack = 8, Size = 268)]
public sealed class STRRET : IDisposable
{
    public STRRET_TYPE uType;
    public IntPtr pOleStr;

    [DllImport("Shlwapi.dll", ExactSpelling = true, SetLastError = false)]
    private static extern int StrRetToBSTR(STRRET pstr, PITEMID_CHILD pidl, [MarshalAs(UnmanagedType.BStr)] out string pbstr);

    ~STRRET()
    {
        Dispose(false);
    }

    public override string ToString()
    {
        return ToString(default(PITEMID_CHILD));
    }

    public string ToString(PITEMID_CHILD pidl)
    {
        if (uType == STRRET_TYPE.WSTR)
        {
            if (pOleStr == IntPtr.Zero)
            {
                return null;
            }

            string str = Marshal.PtrToStringUni(pOleStr);
            return str;
        }
        else
        {
            string str;

            int res = StrRetToBSTR(this, pidl, out str);

            if (res < 0)
            {
                Marshal.ThrowExceptionForHR(res);
            }

            return str;
        }
    }


    #region IDisposable Support

    // This code added to correctly implement the disposable pattern.
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    #endregion

    private void Dispose(bool disposing)
    {
        Marshal.FreeCoTaskMem(pOleStr);
        pOleStr = IntPtr.Zero;
    }
}

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("000214e6-0000-0000-c000-000000000046")]
public interface IShellFolder
{
    void ParseDisplayName(
        IntPtr hwnd,
        IntPtr pbc,
        [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName,
        out int pchEaten,
        out PIDLIST_RELATIVE ppidl,
        ref uint pdwAttributes);

    void EnumObjects(IntPtr hwnd, uint grfFlags, out IEnumIDList ppenumIDList);

    void BindToObject(
        PIDLIST_RELATIVE pidl,
        IntPtr pbc,
        [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
        [MarshalAs(UnmanagedType.IUnknown)] out object ppv);

    void BindToStorage(
        PIDLIST_RELATIVE pidl,
        IntPtr pbc,
        [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
        [MarshalAs(UnmanagedType.IUnknown)] out object ppv);

    [PreserveSig]
    int CompareIDs(IntPtr lParam, PIDLIST_RELATIVE pidl1, PIDLIST_RELATIVE pidl2);

    void CreateViewObject(
        IntPtr hwndOwner,
        [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
        [MarshalAs(UnmanagedType.IUnknown)] out object ppv);

    void GetAttributesOf(
        int cidl,
        [In, MarshalAs(UnmanagedType.LPArray)] LPITEMIDLIST[] apidl,
        ref uint rgfInOut);

    void GetUIObjectOf(
        IntPtr hwndOwner,
        int cidl,
        [In, MarshalAs(UnmanagedType.LPArray)] PITEMID_CHILD[] apidl,
        [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
        IntPtr rgfReserved,
        [MarshalAs(UnmanagedType.IUnknown)] out object ppv);

    void GetDisplayNameOf(
        PITEMID_CHILD pidl,
        uint uFlags,
        STRRET pName);

    void SetNameOf(
        IntPtr hwnd,
        PITEMID_CHILD pidl,
        [MarshalAs(UnmanagedType.LPWStr)] string pszName,
        uint uFlags,
        out PITEMID_CHILD ppidlOut);
}

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("000214f2-0000-0000-c000-000000000046")]
public interface IEnumIDList
{
    void Next(int celt, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] PITEMID_CHILD[] rgelt, out int pceltFetched);

    void Skip(int celt);

    void Reset();

    void Clone(out IEnumIDList ppenum);
}

// Windows >= XP
public static class ShellFolderUtilities
{
    [DllImport("Shell32.dll", ExactSpelling = true, SetLastError = false)]
    public static extern int SHGetSpecialFolderLocation(IntPtr hwnd, int csidl, out PIDLIST_ABSOLUTE ppidl);

    [DllImport("Shell32.dll", ExactSpelling = true, SetLastError = false)]
    public static extern int SHGetDesktopFolder(out IShellFolder ppshf);

    public static readonly int CSIDL_DESKTOP = 0x0000;

    public static readonly int CSIDL_BITBUCKET = 0x000a;

    // https://blogs.msdn.microsoft.com/oldnewthing/20110830-00/?p=9773
    public static void BindToCsidl(int csidl, Guid riid, out object ppv)
    {
        var pidl = default(PIDLIST_ABSOLUTE);

        try
        {
            int res;

            if (csidl != CSIDL_DESKTOP)
            {
                res = SHGetSpecialFolderLocation(IntPtr.Zero, csidl, out pidl);

                if (res < 0)
                {
                    Marshal.ThrowExceptionForHR(res);
                }
            }

            IShellFolder psfDesktop;
            res = SHGetDesktopFolder(out psfDesktop);

            if (res < 0)
            {
                Marshal.ThrowExceptionForHR(res);
            }

            if (csidl == CSIDL_DESKTOP)
            {
                ppv = psfDesktop;
                return;
            }

            psfDesktop.BindToObject(new PIDLIST_RELATIVE { Ptr = pidl.Ptr }, IntPtr.Zero, riid, out ppv);
        }
        finally
        {
            Marshal.FreeCoTaskMem(pidl.Ptr);
        }
    }

    public static IEnumerable<PITEMID_CHILD> Enumerate(this IShellFolder sf)
    {
        IEnumIDList ppenumIDList;
        sf.EnumObjects(IntPtr.Zero, 0x00020 /* SHCONTF_FOLDERS */ | 0x00040 /* SHCONTF_NONFOLDERS */, out ppenumIDList);

        if (ppenumIDList == null)
        {
            yield break;
        }

        var items = new PITEMID_CHILD[1];

        while (true)
        {
            int fetched;

            ppenumIDList.Next(items.Length, items, out fetched);

            if (fetched == 0)
            {
                break;
            }

            yield return items[0];
        }
    }
}

最后是一个使用它的小示例程序......

private static void TestShellFolder()
{
    object recycleBinTemp;
    ShellFolderUtilities.BindToCsidl(ShellFolderUtilities.CSIDL_BITBUCKET, typeof(IShellFolder).GUID, out recycleBinTemp);
    var recycleBin = (IShellFolder)recycleBinTemp;

    var pids = new List<PITEMID_CHILD>();

    try
    {
        foreach (PITEMID_CHILD pidl in recycleBin.Enumerate())
        {
            // Remember to free the pidl!

            string str;

            using (var ret = new STRRET { uType = STRRET_TYPE.CSTR })
            {

                recycleBin.GetDisplayNameOf(pidl, 0, ret);
                str = ret.ToString(pidl);
            }


            // Some condition to include/exclude...
            if (pids.Count < 10)
            {
                Console.WriteLine(str);
                pids.Add(pidl);
            }
            else
            {
                Marshal.FreeCoTaskMem(pidl.Ptr);
            }
        }

        var pids2 = pids.ToArray();

        object cmTemp;
        recycleBin.GetUIObjectOf(IntPtr.Zero, pids2.Length, pids2, typeof(IContextMenu).GUID, IntPtr.Zero, out cmTemp);
        var cm = (IContextMenu)cmTemp;


        // To see verbs
        //var verbsAnsi = ContextMenuUtilities.GetVerbs(cm, true);
        //var verbsUnicode = ContextMenuUtilities.GetVerbs(cm, false);

        var cmd = new CMINVOKECOMMANDINFOEX
        {
            cbSize = Marshal.SizeOf(typeof(CMINVOKECOMMANDINFOEX)),
            fMask = 0x00000400 /* CMIC_MASK_FLAG_NO_UI */,
            lpVerb = "delete",
        };

        cm.InvokeCommand(ref cmd);
    }
    finally
    {
        foreach (var pid in pids)
        {
            Marshal.FreeCoTaskMem(pid.Ptr);
        }
    }
}
于 2017-03-19T07:39:13.357 回答
0

首先将System.Runtime.InteropService添加到您的项目中。我们将使用SHEmptyRecycleBin方法,它接受 3 个参数。之后,通过使用在您的类中导入Shell32.dllDllImport

[DllImport("Shell32.dll")]
static extern int SHEmptyRecycleBin(IntPtr hwnd, string pszRootPath, RecycleFlag dwFlags);

然后为 RecycleBin 标志(dwFlags)定义一个枚举。这些值是十六进制的。

enum RecycleFlag : int
{
    SHERB_NOCONFIRMATION = 0x00000001, // No confirmation
    SHERB_NOPROGRESSUI = 0x00000001, // No progress tracking window 
    SHERB_NOSOUND = 0x00000004 // No sound played
}

将以下代码放在空的回收站按钮中,该按钮调用 Shell32.dll 中的系统方法为:

SHEmptyRecycleBin(IntPtr.Zero, null, RecycleFlag.SHERB_NOSOUND | RecycleFlag.SHERB_NOCONFIRMATION);

参考:这里

于 2017-03-16T08:04:12.107 回答