private void Enumerate() { IntPtr hEnum = IntPtr.Zero; Files.Clear(); try { if (ShellFolderInterface?.EnumObjects(_hwndInput, SHCONTF.FOLDERS | SHCONTF.NONFOLDERS, out hEnum) == NativeMethods.S_OK) { try { IEnumIDList enumIdList = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(hEnum, typeof(IEnumIDList)); while (enumIdList.Next(1, out var pidlChild, out var numFetched) == NativeMethods.S_OK && numFetched == 1) { if (_isDisposed) { break; } AddFile(pidlChild); } Marshal.FinalReleaseComObject(enumIdList); } catch (Exception e) { ShellLogger.Error($"ShellFolder: Exception while enumerating IShellFolder: {e.Message}"); } finally { Marshal.Release(hEnum); } } else { ShellLogger.Error($"ShellFolder: Unable to enumerate IShellFolder"); } } catch (Exception e) { ShellLogger.Error($"ShellFolder: Unable to enumerate IShellFolder: {e.Message}"); } }
/// <summary> /// Gets the children. /// </summary> /// <param name="childTypes">The child types.</param> /// <returns> /// The children. /// </returns> public IEnumerable <ShellItem> GetChildren(ChildTypes childTypes) { // We'll return a list of children. var children = new List <ShellItem>(); // Create the enum flags from the childtypes. SHCONTF enumFlags = 0; if (childTypes.HasFlag(ChildTypes.Folders)) { enumFlags |= SHCONTF.SHCONTF_FOLDERS; } if (childTypes.HasFlag(ChildTypes.Files)) { enumFlags |= SHCONTF.SHCONTF_NONFOLDERS; } if (childTypes.HasFlag(ChildTypes.Hidden)) { enumFlags |= SHCONTF.SHCONTF_INCLUDEHIDDEN; } try { // Create an enumerator for the children. IEnumIDList pEnum; var result = ShellFolderInterface.EnumObjects(IntPtr.Zero, enumFlags, out pEnum); // Validate the result. if (result != 0) { // Throw the failure as an exception. Marshal.ThrowExceptionForHR((int)result); } // TODO: This logic should go in the pidl manager. // Enumerate the children, ten at a time. const int batchSize = 10; var pidlArray = Marshal.AllocCoTaskMem(IntPtr.Size * 10); uint itemsFetched; result = WinError.S_OK; do { result = pEnum.Next(batchSize, pidlArray, out itemsFetched); // Get each pidl. var pidls = new IntPtr[itemsFetched]; Marshal.Copy(pidlArray, pidls, 0, (int)itemsFetched); foreach (var childPidl in pidls) { // Create a new shell folder. var childShellFolder = new ShellItem(); // Initialize it. try { childShellFolder.Initialise(childPidl, this); } catch (Exception exception) { throw new InvalidOperationException("Failed to initialise child.", exception); } // Add the child. children.Add(childShellFolder); // Free the PIDL, reset the result. Marshal.FreeCoTaskMem(childPidl); } } while (result == WinError.S_OK); Marshal.FreeCoTaskMem(pidlArray); // Release the enumerator. if (Marshal.IsComObject(pEnum)) { Marshal.ReleaseComObject(pEnum); } } catch (Exception exception) { throw new InvalidOperationException("Failed to enumerate children.", exception); } // Sort the children. var sortedChildren = children.Where(c => c.IsFolder).ToList(); sortedChildren.AddRange(children.Where(c => !c.IsFolder)); // Return the children. return(sortedChildren); }
/// <summary> /// Gets the children. /// </summary> /// <param name="childTypes">The child types.</param> /// <returns> /// The children. /// </returns> public IEnumerable <ShellItem> GetChildren(ChildTypes childTypes) { // We'll return a list of children. var children = new List <ShellItem>(); // Create the enum flags from the childtypes. SHCONTF enumFlags = SHCONTF.None; if (childTypes.HasFlag(ChildTypes.Folders)) { enumFlags |= SHCONTF.SHCONTF_FOLDERS; } if (childTypes.HasFlag(ChildTypes.Files)) { enumFlags |= SHCONTF.SHCONTF_NONFOLDERS; } if (childTypes.HasFlag(ChildTypes.Hidden)) { enumFlags |= SHCONTF.SHCONTF_INCLUDEHIDDEN; } try { // Create an enumerator for the children. IEnumIDList pEnum; var result = ShellFolderInterface.EnumObjects(IntPtr.Zero, enumFlags, out pEnum); // Validate the result. if (result != 0) { // Throw the failure as an exception. Marshal.ThrowExceptionForHR((int)result); } // Start going through children. IntPtr childPIDL; int enumResult; pEnum.Next(1, out childPIDL, out enumResult); // Now start enumerating. while (childPIDL != IntPtr.Zero && enumResult == 1) { // Create a new shell folder. var childShellFolder = new ShellItem(); // Initialize it. try { childShellFolder.Initialise(childPIDL, this); } catch (Exception exception) { throw new InvalidOperationException("Failed to initialise child.", exception); } // Add the child. children.Add(childShellFolder); // Free the PIDL, reset the result. Marshal.FreeCoTaskMem(childPIDL); // Move onwards. pEnum.Next(1, out childPIDL, out enumResult); } // Release the enumerator. Marshal.ReleaseComObject(pEnum); } catch (Exception exception) { throw new InvalidOperationException("Failed to enumerate children.", exception); } // Sort the children. var sortedChildren = children.Where(c => c.IsFolder).ToList(); sortedChildren.AddRange(children.Where(c => !c.IsFolder)); // Return the children. return(sortedChildren); }