2017-03-16 88 views
0

enter image description here如何使用C#從recyclebin中刪除多選項目?

如何通過C#或windows api刪除多項,我已經搜索了很長時間沒有解決方案。我使用Shell32.dll中的FolderItemVerb逐個刪除文件,但它會同時彈出一個對話框。如果你知道如何解決這個問題,我將不勝感激。謝謝。

+0

也許[這](http://www.c-sharpcorner.com/UploadFile/167ad2/empty-recycle -bin-using-C-Sharp /)可以幫助你... – Nino

+0

C中有一個例子:https://blogs.msdn.microsoft.com/oldnewthing/20110901-00/?p = 9753 /你需要的是一個開始於:* //在一個真正的程序中,你不會硬編碼一個固定的限制* – xanatos

+0

你現在怎麼操作shell?您是使用WindowsAPICode包還是導入了COM對象? – xanatos

回答

0

首先將System.Runtime.InteropService添加到您的項目中。我們將使用SHEmptyRecycleBin方法,它接受3個參數。 之後,通過使用DllImport在您的課程中導入Shell32.dll

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

參考:here

+0

感謝您的回答,但我不想清空回收站,我只想刪除選定的文件。 – roy

0

這不是微弱心!

代碼兼容Windows> = Vista,沒有XP! XP代碼在結尾

這是我第一次看看Shell32接口......哇......即使是最簡單的事情也很複雜:-)但是,COM總是很複雜。現在...有2.5個競爭的數據結構/接口用於處理Shell中的文件... IShellFolder(舊的COM接口,本示例中未使用),IShellItem(此示例中使用的新COM接口),IDLIST (這裏用作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_ABSOLUTEList<>,從List<>創建IShellItemArray,對IShellItemArray綁定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); 
     } 
    } 
}