Skip to content

Instantly share code, notes, and snippets.

@smourier
Created December 8, 2017 23:12
Show Gist options
  • Save smourier/c7771d4d5351c702f94118a0244856c8 to your computer and use it in GitHub Desktop.
Save smourier/c7771d4d5351c702f94118a0244856c8 to your computer and use it in GitHub Desktop.
Enum Shell Folders
static void Interop()
{
SHCreateItemFromParsingName("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", IntPtr.Zero, typeof(IShellItem).GUID, out IShellItem item);
item.BindToHandler(IntPtr.Zero, BHID_SFObject, typeof(IShellFolder).GUID, out IShellFolder folder);
folder.EnumObjects(IntPtr.Zero, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, out IEnumIDList list);
do
{
list.Next(1, out IntPtr pidl, out int fetched);
if (fetched == 0)
break;
folder.GetDisplayNameOf(ILFindLastID(pidl), 0, out STRRET name);
Console.WriteLine(Marshal.PtrToStringUni(name.pOleStr));
Marshal.FreeCoTaskMem(name.pOleStr);
Marshal.FreeCoTaskMem(pidl);
}
while (true);
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct STRRET
{
public int uType;
public IntPtr pOleStr;
}
private const int SHCONTF_FOLDERS = 0x00020;
private const int SHCONTF_NONFOLDERS = 0x00040;
private static readonly Guid BHID_SFObject = new Guid("3981e224-f559-11d3-8e3a-00c04f6837d5");
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
private static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string path, IntPtr pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem shellItem);
[DllImport("shell32.dll")]
private static extern IntPtr ILFindLastID(IntPtr pidl);
[Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IShellItem
{
void BindToHandler(IntPtr pbc, Guid bhid, Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out IShellFolder ppv);
}
[Guid("000214e6-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IShellFolder
{
void ParseDisplayName();
[PreserveSig]
int EnumObjects(IntPtr hwnd, int grfFlags, [MarshalAs(UnmanagedType.Interface)] out IEnumIDList ppenumIDList);
void BindToObject();
void BindToStorage();
void CompareIDs();
void CreateViewObject();
void GetAttributesOf();
void GetUIObjectOf();
int GetDisplayNameOf(IntPtr pidl, int uFlags, out STRRET pName);
}
[Guid("000214f2-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IEnumIDList
{
[PreserveSig]
int Next(int celt, out IntPtr rgelt, out int pceltFetched);
}
@deakjahn
Copy link

deakjahn commented Dec 9, 2017

var riid1 = typeof(IShellItem).GUID;
SHCreateItemFromParsingName("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", IntPtr.Zero, ref riid1, out IShellItem item);
var BHID_SFObject = new Guid("3981e224-f559-11d3-8e3a-00c04f6837d5");
var riid2 = typeof(IShellFolder).GUID;
item.BindToHandler(IntPtr.Zero, ref BHID_SFObject, ref riid2, out IShellFolder folder);
folder.EnumObjects(IntPtr.Zero, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, out IEnumIDList list);

private static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string path, IntPtr pbc, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem shellItem);

void BindToHandler(IntPtr pbc, ref Guid bhid, ref Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out IShellFolder ppv);

@deakjahn
Copy link

deakjahn commented Dec 9, 2017

Using IEnumShellItems:

  var riid1 = typeof(IShellItem).GUID;
  SHCreateItemFromParsingName("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", IntPtr.Zero, ref riid1, out IShellItem folder);
  var BHID_EnumItems = new Guid("94f60519-2850-4924-aa5a-d15e84868039");
  var riid2 = typeof(IEnumShellItems).GUID;
  folder.BindToHandler(IntPtr.Zero, ref BHID_EnumItems, ref riid2, out IEnumShellItems items);
  do {
    items.Next(1, out IShellItem child, out uint fetched);
    if (fetched == 0)
      break;

    child.GetDisplayName(SIGDN_NORMALDISPLAY, out string name);
    child.GetDisplayName(SIGDN_FILESYSPATH, out string path);
    Console.WriteLine($"{name} = {path}");
  }
  while (true);

private const int SIGDN_NORMALDISPLAY = 0x00000000;
private const int SIGDN_FILESYSPATH = unchecked((int)0x80058000);

[ComImport, Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IShellItem {
  void BindToHandler(IntPtr pbc, ref Guid bhid, ref Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out IEnumShellItems ppv);
  void GetParent([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi);
  int GetDisplayName([In] int sigdnName, [Out, MarshalAs(UnmanagedType.LPWStr)] out string ppszName);
}

[ComImport, Guid("70629033-E363-4A28-A567-0DB78006E6D7"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IEnumShellItems {
  int Next(uint celt, out IShellItem rgelt, out uint pceltFetched);
  int Skip([In] uint celt);
  int Reset();
  int Clone([MarshalAs(UnmanagedType.Interface)] out IEnumShellItems ppenum);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment