internal FileInfoEx(DirectoryInfoEx parentDir, PIDL relPIDL) { Parent = parentDir; //0.15: Fixed ShellFolder not freed. using (ShellFolder2 parentShellFolder = parentDir.ShellFolder) init(parentShellFolder, parentDir.PIDLRel, relPIDL); }
/// <summary> /// Rename a file or folder in an directory. /// </summary> public static void Rename(string source, string destName) { //DirectoryInfoEx srcDir = new DirectoryInfoEx(Path.GetDirectoryName(source)); FileSystemInfoEx srcElement = new FileSystemInfoEx(source); string srcName = Path.GetFileName(source); if (!srcElement.Exists || srcElement.Parent == null) { throw new IOException("Source not exists"); } //0.15: Fixed ShellFolder not freed. using (ShellFolder2 srcParentShellFolder = srcElement.Parent.ShellFolder) { if (srcParentShellFolder == null) { throw new IOException("Source directory does not support IShellFolder"); } IntPtr tmpPtr; int hr = srcParentShellFolder.SetNameOf(IntPtr.Zero, srcElement.PIDLRel.Ptr, destName, ShellAPI.SHGNO.FORPARSING, out tmpPtr); PIDL tmpPIDL = new PIDL(tmpPtr, false); //consume the IntPtr, and free it. tmpPIDL.Free(); if (hr != ShellAPI.S_OK) { Marshal.ThrowExceptionForHR(hr); } } }
private ShellFolder2 getIShellFolder() { if (this.FullName.Equals(IOTools.IID_Desktop)) { return(getDesktopShellFolder()); } else { ShellFolder2 retVal = getIShellFolderFromParent(); if (retVal != null) { return(retVal); } return(this.RequestPIDL((pidl, relPIDL) => { using (ShellFolder2 parentShellFolder = getParentIShellFolder(pidl, out relPIDL)) { IntPtr ptrShellFolder; int hr = parentShellFolder.BindToObject(relPIDL.Ptr, IntPtr.Zero, ref ShellAPI.IID_IShellFolder2, out ptrShellFolder); if (ptrShellFolder == IntPtr.Zero || hr != ShellAPI.S_OK) { Marshal.ThrowExceptionForHR(hr); } return new ShellFolder2(ptrShellFolder); } })); } }
//internal static string getParentParseName(PIDL pidl) //{ // PIDL relPIDL; // PIDL parentPIDL = getParentPIDL(pidl, out relPIDL); // IShellFolder sf = getParentIShellFolder(parentPIDL, out relPIDL); // if (relPIDL.Size == 0) // return IOTools.IID_Desktop; // return loadName(sf, relPIDL, ShellAPI.SHGNO.FORPARSING); //} internal static ShellFolder2 getParentIShellFolder(PIDL pidl, out PIDL relPIDL) { int hr; IntPtr ptrShellFolder = IntPtr.Zero; if (pidl.Size == 0 || PIDL.ILFindLastID(pidl.Ptr) == pidl.Ptr || //is root or parent is root PIDLToPath(pidl) == Environment.GetFolderPath(Environment.SpecialFolder.Desktop)) { hr = ShellAPI.SHGetDesktopFolder(out ptrShellFolder); relPIDL = new PIDL(pidl, true); } else { PIDL parentPIDL = getParentPIDL(pidl, out relPIDL); //Console.WriteLine("ParentPIDL.Size = {0}", parentPIDL.Size); Guid guid = ShellAPI.IID_IShellFolder2; using (ShellFolder2 _desktopShellFolder = getDesktopShellFolder()) hr = _desktopShellFolder.BindToObject(parentPIDL.Ptr, IntPtr.Zero, ref guid, out ptrShellFolder); if (parentPIDL != null) { parentPIDL.Free(); } } if (hr == ShellAPI.S_OK && ptrShellFolder != IntPtr.Zero) { return(new ShellFolder2(ptrShellFolder)); } Marshal.ThrowExceptionForHR(hr); return(null); //mute error. }
/// <summary> /// Refresh the file / directory info. Does not refresh directory contents /// because it refresh every time GetFiles/Directories/FileSystemInfos is called. /// </summary> public void Refresh(RefreshModeEnum mode = RefreshModeEnum.AllProps) { RefreshMode |= mode; //0.23 : Delay loading some properties. PIDL relPIDL = null; if (!Exists) { refresh(null, null, null, mode); } else { try { //0.16: Fixed ShellFolder not freed this.RequestPIDL(pidlLookup => { using (ShellFolder2 sf = getParentIShellFolder(pidlLookup, out relPIDL)) refresh(sf, relPIDL, pidlLookup, mode); }); } catch (NullReferenceException) { refresh(null, null, null, mode); } }
internal FileInfoEx(DirectoryInfoEx parentDir, PIDL relPIDL) { Parent = parentDir; //0.15: Fixed ShellFolder not freed. using (ShellFolder2 parentShellFolder = parentDir.ShellFolder) parentDir.RequestRelativePIDL(parentRelPidl => init(parentShellFolder, parentRelPidl, relPIDL)); }
internal static string PIDLToPath(PIDL pidlFull) { if (DirectoryInfoEx.DesktopDirectory.RequestPIDL(desktopPIDL => pidlFull.Equals(desktopPIDL))) { return("::{00021400-0000-0000-C000-000000000046}"); } using (ShellFolder2 _desktopShellFolder = getDesktopShellFolder()) return(loadName(_desktopShellFolder, pidlFull, ShellAPI.SHGNO.FORPARSING)); }
internal DirectoryInfoEx(DirectoryInfoEx parentDir, PIDL relPIDL) { Parent = parentDir; parentDir.RequestPIDL(parentPIDL => { //0.15: Fixed ShellFolder not freed. using (ShellFolder2 parentShellFolder = parentDir.ShellFolder) init(parentShellFolder, parentPIDL, relPIDL); }); }
/// <summary> /// Take a directory and return the IStorage PTr interface. /// </summary> internal static bool getIStorage(DirectoryInfoEx dir, out IntPtr storagePtr) { //0.19 Fixed ArgumentException when getting storage of C:\{User}\Desktop. if (dir.FullName.Equals(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory))) { dir = DirectoryInfoEx.DesktopDirectory; } IntPtr storePtr = IntPtr.Zero; //0.15 : Fixed PIDL not freed correctly. try { return(dir.RequestRelativePIDL(dirPIDLRel => { int hr; if (dirPIDLRel.Size == 0) { IntPtr pidlLast = IntPtr.Zero; hr = ShellAPI.SHBindToParent(dirPIDLRel.Ptr, ShellAPI.IID_IStorage, out storePtr, ref pidlLast); } else { //0.15: Fixed ShellFolder not freed correctly. using (ShellFolder2 dirParentShellFolder = dir.Parent.ShellFolder) if (dirParentShellFolder != null) { hr = dirParentShellFolder.BindToStorage( dirPIDLRel.Ptr, IntPtr.Zero, ref ShellAPI.IID_IStorage, out storePtr); } else { storePtr = IntPtr.Zero; return false; } } if ((hr != ShellAPI.S_OK)) { storePtr = IntPtr.Zero; Marshal.ThrowExceptionForHR(hr); return false; } return true; })); } finally { storagePtr = storePtr; } }
/// <summary> /// Convert a Parsable path to PIDL /// </summary> private static PIDL PathtoPIDL(string path) { IntPtr pidlPtr; uint pchEaten = 0; ShellAPI.SFGAO pdwAttributes = 0; using (ShellFolder2 _desktopShellFolder = getDesktopShellFolder()) _desktopShellFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, path, ref pchEaten, out pidlPtr, ref pdwAttributes); PIDL pidl = new PIDL(pidlPtr, false); return(pidl); }
internal static ShellFolder2 getDesktopShellFolder() { IntPtr ptrShellFolder; int hr = ShellAPI.SHGetDesktopFolder(out ptrShellFolder); if (hr == ShellAPI.S_OK && ptrShellFolder != IntPtr.Zero) { ShellFolder2 sf = new ShellFolder2(ptrShellFolder); //0.13: Fixed? Desktop ShellFolder not released. (may be a cause of AccessViolationException.) //GC.SuppressFinalize(sf); return(sf); } Marshal.ThrowExceptionForHR(hr); return(null); //mute error. }
internal DirectoryInfoEx(DirectoryInfoEx parentDir, PIDL relPIDL) { Parent = parentDir; PIDL parentPIDL = parentDir.PIDL; try { //0.15: Fixed ShellFolder not freed. using (ShellFolder2 parentShellFolder = parentDir.ShellFolder) init(parentShellFolder, parentPIDL, relPIDL); } finally { if (parentPIDL != null) { parentPIDL.Free(); } parentPIDL = null; } }
internal static string PIDLToPath(PIDL pidlFull) { PIDL desktopPIDL = DirectoryInfoEx.DesktopDirectory.PIDL; if (pidlFull.Equals(desktopPIDL)) { return("::{00021400-0000-0000-C000-000000000046}"); } if (desktopPIDL != null) { desktopPIDL.Free(); } desktopPIDL = null; using (ShellFolder2 _desktopShellFolder = getDesktopShellFolder()) return(loadName(_desktopShellFolder, pidlFull, ShellAPI.SHGNO.FORPARSING)); }
private ShellFolder2 getIShellFolder() { if (this.FullName.Equals(IOTools.IID_Desktop)) { return(getDesktopShellFolder()); } else { ShellFolder2 retVal = getIShellFolderFromParent(); if (retVal != null) { return(retVal); } PIDL pidlLookup = PIDL; PIDL relPIDL = this.PIDLRel; try { using (ShellFolder2 parentShellFolder = getParentIShellFolder(pidlLookup, out relPIDL)) { IntPtr ptrShellFolder; int hr = parentShellFolder.BindToObject(relPIDL.Ptr, IntPtr.Zero, ref ShellAPI.IID_IShellFolder2, out ptrShellFolder); if (ptrShellFolder == IntPtr.Zero || hr != ShellAPI.S_OK) { Marshal.ThrowExceptionForHR(hr); } return(new ShellFolder2(ptrShellFolder)); } } finally { if (pidlLookup != null) { pidlLookup.Free(); } if (relPIDL != null) { relPIDL.Free(); } relPIDL = null; pidlLookup = null; } } }
private ShellFolder2 getIShellFolderFromParent() { if (_parent != null) { using (ShellFolder2 parentShellFolder = _parent.ShellFolder) { IntPtr ptrShellFolder; PIDL relPIDL = this.PIDLRel; int hr = parentShellFolder.BindToObject(relPIDL.Ptr, IntPtr.Zero, ref ShellAPI.IID_IShellFolder2, out ptrShellFolder); if (ptrShellFolder != IntPtr.Zero && hr == ShellAPI.S_OK) { return(new ShellFolder2(ptrShellFolder)); } } } return(null); }
internal static PIDL PathToPIDL(string path) { path = Helper.RemoveSlash(path); IntPtr pidlPtr; uint pchEaten = 0; ShellAPI.SFGAO pdwAttributes = 0; using (ShellFolder2 _desktopShellFolder = getDesktopShellFolder()) { int hr = _desktopShellFolder.ParseDisplayName( IntPtr.Zero, IntPtr.Zero, path, ref pchEaten, out pidlPtr, ref pdwAttributes); if (pidlPtr == IntPtr.Zero || hr != ShellAPI.S_OK) { /*Marshal.ThrowExceptionForHR(hr);*/ return(null); } //Commented because this is part of init and it's too time consuming. } return(new PIDL(pidlPtr, false)); }
/// <summary> /// Refresh the file / directory info. Does not refresh directory contents /// because it refresh every time GetFiles/Directories/FileSystemInfos is called. /// </summary> public new void Refresh() { PIDL relPIDL = null; if (!Exists) { refresh(null, null, null); } else { try { //0.16: Fixed ShellFolder not freed using (ShellFolder2 sf = getParentIShellFolder(PIDL, out relPIDL)) refresh(sf, relPIDL, PIDL); } catch (NullReferenceException) { refresh(null, null, null); } }
private bool getExists() { if (FullName == "::{00021400-0000-0000-C000-000000000046}") //Desktop { return(true); } else if (FullName == null) { return(false); } else { try { if (_pidl != null) { using (ShellFolder2 _desktopShellFolder = getDesktopShellFolder()) loadName(_desktopShellFolder, _pidl, ShellAPI.SHGNO.FORPARSING); return(true); } else { PIDL pidlLookup = PathToPIDL(FullName); try { return(pidlLookup != null); } finally { if (pidlLookup != null) { pidlLookup.Free(); } } } } catch (FileNotFoundException) { return(false); } } }
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); } } }
internal static string PtrToPath(IntPtr ptr) { using (ShellFolder2 _desktopShellFolder = getDesktopShellFolder()) return(loadName(_desktopShellFolder, ptr, ShellAPI.SHGNO.FORPARSING)); }
//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); } } }