public IEnumerable <DirectoryInfoEx> EnumerateDirectories(String searchPattern, SearchOption searchOption, CancelDelegate cancel) { IntPtr ptrEnum = IntPtr.Zero; IEnumIDList IEnum = null; PIDL parentPIDL = this.PIDL; using (ShellFolder2 sf = this.ShellFolder) try { if (sf.EnumObjects(IntPtr.Zero, flag, out ptrEnum) == ShellAPI.S_OK) { IEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(ptrEnum, typeof(IEnumIDList)); IntPtr pidlSubItem; int celtFetched; while (!IOTools.IsCancelTriggered(cancel) && IEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1) { ShellAPI.SFGAO attribs = ShellAPI.SFGAO.FOLDER | ShellAPI.SFGAO.FILESYSTEM | ShellAPI.SFGAO.STREAM | ShellAPI.SFGAO.FILESYSANCESTOR | ShellAPI.SFGAO.NONENUMERATED; sf.GetAttributesOf(1, new IntPtr[] { pidlSubItem }, ref attribs); bool isZip = ((attribs & ShellAPI.SFGAO.FOLDER) != 0 && (attribs & ShellAPI.SFGAO.STREAM) != 0); bool isDir = ((attribs & ShellAPI.SFGAO.FOLDER) != 0); //0.18 Added a check for NonEnumerated items so DirectoryInfoEx.EnumerateDirectories wont return some system directories (e.g. C:\MSOCache) //bool isNonEnumerated = ((attribs & ShellAPI.SFGAO.NONENUMERATED) != 0); bool isFileAncestor = ((attribs & ShellAPI.SFGAO.FILESYSANCESTOR) != 0); bool includedFolder = false; if (!isZip && !isFileAncestor) //0.14 : Added allowed folder list so Non-FileAncestor directory (e.g. recycle-bin) is listed. { string[] allowedPaths = new string[] { "::{645FF040-5081-101B-9F08-00AA002F954E}" }; string path = PIDLToPath(new PIDL(pidlSubItem, false)); foreach (string allowedPath in allowedPaths) { if (allowedPath == path) { includedFolder = true; } } if (!includedFolder) { if (IOTools.HasParent(this, NetworkDirectory)) { includedFolder = true; } } } if (isDir && !isZip /*&& !isNonEnumerated*/ && (isFileAncestor || includedFolder)) { PIDL subPidl = new PIDL(pidlSubItem, false); //DirectoryInfoEx di = new DirectoryInfoEx(this, subPidl); //0.22: Fix illegal PIDL for Directory under Library.ms directory bool isLibraryItem = IOTools.IsLibraryItem(FullName); DirectoryInfoEx di = new DirectoryInfoEx(sf, parentPIDL, subPidl, isLibraryItem); if (IOTools.MatchFileMask(di.Name, searchPattern)) { yield return(di); } if (searchOption == SearchOption.AllDirectories) { IEnumerator <DirectoryInfoEx> dirEnumerator = di.EnumerateDirectories(searchPattern, searchOption, cancel).GetEnumerator(); while (dirEnumerator.MoveNext()) { //Debug.Assert(dirEnumerator.Current.IsFolder); yield return(dirEnumerator.Current); } } } } } } finally { if (parentPIDL != null) { parentPIDL.Free(); parentPIDL = null; } if (IEnum != null) { Marshal.ReleaseComObject(IEnum); Marshal.Release(ptrEnum); } } }
//0.17: Added DirectoryInfoEx.EnumerateFiles/EnumerateDirectories/EnumerateFileSystemInfos() methods which work similar as the one in .Net4 public IEnumerable <FileInfoEx> EnumerateFiles(String searchPattern, SearchOption searchOption, CancelDelegate cancel) { IntPtr ptrEnum = IntPtr.Zero; IEnumIDList IEnum = null; PIDL parentPIDL = this.PIDL; using (ShellFolder2 sf = this.ShellFolder) try { if (sf.EnumObjects(IntPtr.Zero, flag, out ptrEnum) == ShellAPI.S_OK) { IEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(ptrEnum, typeof(IEnumIDList)); IntPtr pidlSubItem; int celtFetched; while (!IOTools.IsCancelTriggered(cancel) && IEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1) { ShellAPI.SFGAO attribs = ShellAPI.SFGAO.FOLDER | ShellAPI.SFGAO.FILESYSTEM | ShellAPI.SFGAO.STREAM; sf.GetAttributesOf(1, new IntPtr[] { pidlSubItem }, ref attribs); //http://www.eggheadcafe.com/aspnet_answers/platformsdkshell/Mar2006/post26165601.asp bool isZip = ((attribs & ShellAPI.SFGAO.FOLDER) != 0 && (attribs & ShellAPI.SFGAO.STREAM) != 0); bool isDir = ((attribs & ShellAPI.SFGAO.FOLDER) != 0); if (isZip || !isDir) { PIDL subRelPidl = new PIDL(pidlSubItem, false); //FileInfoEx fi = new FileInfoEx(sf, this, subRelPidl); FileInfoEx fi = new FileInfoEx(sf, parentPIDL, subRelPidl); if (IOTools.MatchFileMask(fi.Name, searchPattern)) { yield return(fi); } //0.18: Fixed DirectoryInfoEx.EnumerateFiles, SearchPattern is ignored. } } if (searchOption == SearchOption.AllDirectories) { IEnumerator <DirectoryInfoEx> dirEnumerator = EnumerateDirectories("*", SearchOption.TopDirectoryOnly, cancel).GetEnumerator(); while (!IOTools.IsCancelTriggered(cancel) && dirEnumerator.MoveNext()) { IEnumerator <FileInfoEx> fileEnumerator = dirEnumerator.Current.EnumerateFiles(searchPattern, searchOption, cancel).GetEnumerator(); while (fileEnumerator.MoveNext()) { //Debug.Assert(!fileEnumerator.Current.IsFolder); yield return(fileEnumerator.Current); } } } } } finally { if (parentPIDL != null) { parentPIDL.Free(); parentPIDL = null; } if (IEnum != null) { Marshal.ReleaseComObject(IEnum); Marshal.Release(ptrEnum); } } }