public static string GetDisplayName(DirectoryInfoEx dx) { IntPtr pidl; uint pchEaten = 0; var sfgao = new ShellAPI.SFGAO(); DirectoryInfoEx.DesktopDirectory.ShellFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, dx.FullName, ref pchEaten, out pidl, ref sfgao); var ptrStr = Marshal.AllocCoTaskMem(ShellAPI.MAX_PATH * 2 + 4); Marshal.WriteInt32(ptrStr, 0, 0); var buf = new StringBuilder(ShellAPI.MAX_PATH); try { DirectoryInfoEx.DesktopDirectory.ShellFolder.GetDisplayNameOf(pidl, ShellAPI.SHGNO.NORMAL, ptrStr); ShellAPI.StrRetToBuf(ptrStr, pidl, buf, ShellAPI.MAX_PATH); } finally { if (ptrStr != IntPtr.Zero) { Marshal.FreeCoTaskMem(ptrStr); } ptrStr = IntPtr.Zero; } return(buf.ToString()); }
private static FileAttributes loadAttributes(IShellFolder2 iShellFolder, PIDL pidlFull, PIDL pidlRel) { FileAttributes retVal = new FileAttributes(); //ShellAPI.SFGAO attribute = shGetFileAttribute(pidlFull, ShellAPI.SFGAO.READONLY | // ShellAPI.SFGAO.FOLDER | ShellAPI.SFGAO.FILESYSTEM | ShellAPI.SFGAO.STREAM | ShellAPI.SFGAO.FILESYSANCESTOR | // ShellAPI.SFGAO.HIDDEN); ShellAPI.SFGAO attribute = ShellAPI.SFGAO.READONLY | ShellAPI.SFGAO.FOLDER | ShellAPI.SFGAO.FILESYSTEM | ShellAPI.SFGAO.STREAM | ShellAPI.SFGAO.FILESYSANCESTOR; iShellFolder.GetAttributesOf(1, new IntPtr[] { pidlRel.Ptr }, ref attribute); if (!IOTools.IsZip(attribute) && (attribute & ShellAPI.SFGAO.FOLDER) != 0) { retVal |= FileAttributes.Directory; } if ((attribute & ShellAPI.SFGAO.HIDDEN) != 0) { retVal |= FileAttributes.Hidden; } if ((attribute & ShellAPI.SFGAO.READONLY) != 0) { retVal |= FileAttributes.ReadOnly; } return(retVal); }
/// <summary> /// Get the PIDLs /// </summary> /// <param name="arrayOfFileInfo">Array of FileInfo</param> /// <returns>Array of PIDLs</returns> protected IntPtr[] GetPIDL(FileInfo[] arrayOfFileInfo) { if (null == arrayOfFileInfo || 0 == arrayOfFileInfo.Length) { return(null); } IShellFolder oParentFolder = GetParentFolder(arrayOfFileInfo[0].DirectoryName); if (null == oParentFolder) { return(null); } var arrPIDL = new IntPtr[arrayOfFileInfo.Length]; int n = 0; foreach (FileInfo fi in arrayOfFileInfo) { // Get the file relative to folder uint pchEaten = 0; ShellAPI.SFGAO pdwAttributes = 0; IntPtr pPIDL; int nResult = oParentFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, fi.Name, ref pchEaten, out pPIDL, ref pdwAttributes); if (S_OK != nResult) { FreePIDL(arrPIDL); return(null); } arrPIDL[n] = pPIDL; n++; } return(arrPIDL); }
protected override void refresh(IShellFolder2 parentShellFolder, PIDL relPIDL, PIDL fullPIDL, RefreshModeEnum mode) { base.refresh(parentShellFolder, relPIDL, fullPIDL, mode); if ((mode & RefreshModeEnum.FullProps) != 0 && parentShellFolder != null && relPIDL != null && fullPIDL != null) { if (!FullName.StartsWith("::") && File.Exists(FullName)) { try { FileInfo fi = new FileInfo(FullName); IsReadOnly = fi.IsReadOnly; Attributes = fi.Attributes; Length = fi.Length; LastAccessTime = fi.LastAccessTime; LastWriteTime = fi.LastWriteTime; CreationTime = fi.CreationTime; } catch { } } else //0.18: Uses File to return FileInfo by default { ShellAPI.SFGAO attribute = shGetFileAttribute(fullPIDL, ShellAPI.SFGAO.READONLY); IsReadOnly = (attribute & ShellAPI.SFGAO.READONLY) != 0; Length = 0; } } }
protected override void refresh(IShellFolder2 parentShellFolder, PIDL relPIDL, PIDL fullPIDL) { base.refresh(parentShellFolder, relPIDL, fullPIDL); if (parentShellFolder != null && relPIDL != null && fullPIDL != null) { ShellAPI.SFGAO attribute = shGetFileAttribute(fullPIDL, ShellAPI.SFGAO.BROWSABLE | ShellAPI.SFGAO.FILESYSTEM | ShellAPI.SFGAO.HASSUBFOLDER); IsBrowsable = (attribute & ShellAPI.SFGAO.BROWSABLE) != 0 || (attribute & ShellAPI.SFGAO.CONTENTSMASK) != 0; IsFileSystem = (attribute & ShellAPI.SFGAO.FILESYSTEM) != 0; HasSubFolder = (attribute & ShellAPI.SFGAO.HASSUBFOLDER) != 0; if (!FullName.StartsWith("::") && Directory.Exists(FullName)) { try { DirectoryInfo di = new DirectoryInfo(FullName); Attributes = di.Attributes; LastAccessTime = di.LastAccessTime; LastWriteTime = di.LastWriteTime; CreationTime = di.CreationTime; } catch { } } initDirectoryType(); } }
private void InitVars() { IntPtr tempPidl; ShellAPI.SHFILEINFO info; //My Computer info = new ShellAPI.SHFILEINFO(); tempPidl = IntPtr.Zero; ShellAPI.SHGetSpecialFolderLocation(IntPtr.Zero, ShellAPI.CSIDL.DRIVES, out tempPidl); ShellAPI.SHGetFileInfo(tempPidl, 0, ref info, ShellAPI.cbFileInfo, ShellAPI.SHGFI.PIDL | ShellAPI.SHGFI.DISPLAYNAME | ShellAPI.SHGFI.TYPENAME); sysfolderName = info.szTypeName; mycompName = info.szDisplayName; Marshal.FreeCoTaskMem(tempPidl); // //Dekstop tempPidl = IntPtr.Zero; ShellAPI.SHGetSpecialFolderLocation(IntPtr.Zero, ShellAPI.CSIDL.DESKTOP, out tempPidl); IntPtr desktopFolderPtr; ShellAPI.SHGetDesktopFolder(out desktopFolderPtr); desktopItem = new ShellItem(this, tempPidl, desktopFolderPtr); // //My Documents uint pchEaten = 0; ShellAPI.SFGAO pdwAttributes = 0; desktopItem.ShellFolder.ParseDisplayName( IntPtr.Zero, IntPtr.Zero, "::{450d8fba-ad25-11d0-98a8-0800361b1103}", ref pchEaten, out tempPidl, ref pdwAttributes); info = new ShellAPI.SHFILEINFO(); ShellAPI.SHGetFileInfo(tempPidl, 0, ref info, ShellAPI.cbFileInfo, ShellAPI.SHGFI.PIDL | ShellAPI.SHGFI.DISPLAYNAME); mydocsName = info.szDisplayName; Marshal.FreeCoTaskMem(tempPidl); StringBuilder path = new StringBuilder(ShellAPI.MAX_PATH); ShellAPI.SHGetFolderPath( IntPtr.Zero, ShellAPI.CSIDL.PERSONAL, IntPtr.Zero, ShellAPI.SHGFP.TYPE_CURRENT, path); mydocsPath = path.ToString(); // }
/// <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); }
protected static ShellAPI.SFGAO shGetFileAttribute(PIDL pidl, ShellAPI.SFGAO lookup) { ShellAPI.SHFILEINFO shfi = new ShellAPI.SHFILEINFO(); shfi.dwAttributes = ShellAPI.SFGAO.READONLY | ShellAPI.SFGAO.HIDDEN | ShellAPI.SFGAO.BROWSABLE | ShellAPI.SFGAO.FILESYSTEM | ShellAPI.SFGAO.HASSUBFOLDER; ShellAPI.SHGFI dwFlag = ShellAPI.SHGFI.PIDL | ShellAPI.SHGFI.ATTRIBUTES | ShellAPI.SHGFI.ATTR_SPECIFIED | ShellAPI.SHGFI.USEFILEATTRIBUTES; ShellAPI.FILE_ATTRIBUTE dwAttr = 0; int cbFileInfo = Marshal.SizeOf(shfi.GetType()); IntPtr retPtr = ShellAPI.SHGetFileInfo(pidl.Ptr, dwAttr, ref shfi, cbFileInfo, dwFlag); if (retPtr.ToInt32() != ShellAPI.S_OK && retPtr.ToInt32() != 1) { Marshal.ThrowExceptionForHR(retPtr.ToInt32()); } return(shfi.dwAttributes); }
/// <summary> /// Gets the parent folder /// </summary> /// <param name="folderName">Folder path</param> /// <returns>IShellFolder for the folder (relative from the desktop)</returns> private IShellFolder GetParentFolder(string folderName) { if (null == _oParentFolder) { IShellFolder oDesktopFolder = GetDesktopFolder(); if (null == oDesktopFolder) { return(null); } // Get the PIDL for the folder file is in IntPtr pPIDL; uint pchEaten = 0; ShellAPI.SFGAO pdwAttributes = 0; int nResult = oDesktopFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, folderName, ref pchEaten, out pPIDL, ref pdwAttributes); if (S_OK != nResult) { return(null); } IntPtr pStrRet = Marshal.AllocCoTaskMem(MAX_PATH * 2 + 4); Marshal.WriteInt32(pStrRet, 0, 0); _oDesktopFolder.GetDisplayNameOf(pPIDL, SHGNO.FORPARSING, pStrRet); var strFolder = new StringBuilder(MAX_PATH); StrRetToBuf(pStrRet, pPIDL, strFolder, MAX_PATH); Marshal.FreeCoTaskMem(pStrRet); _strParentFolder = strFolder.ToString(); // Get the IShellFolder for folder IntPtr pUnknownParentFolder; nResult = oDesktopFolder.BindToObject(pPIDL, IntPtr.Zero, ref IID_IShellFolder, out pUnknownParentFolder); // Free the PIDL first Marshal.FreeCoTaskMem(pPIDL); if (S_OK != nResult) { return(null); } _oParentFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(pUnknownParentFolder, typeof(IShellFolder)); } return(_oParentFolder); }
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> /// Sets the attributes for a file ShellItem /// </summary> private void SetFileAttributes() { // file attributes to retrieve with GetAttributesOf ShellAPI.SFGAO attr = ShellAPI.SFGAO.LINK | ShellAPI.SFGAO.SHARE | ShellAPI.SFGAO.FILESYSTEM | ShellAPI.SFGAO.HIDDEN | ShellAPI.SFGAO.CANRENAME | ShellAPI.SFGAO.STREAM; parent.folder.GetAttributesOf(1, new IntPtr[] { relPidl.Ptr }, ref attr); isFolder = false; isLink = (attr & ShellAPI.SFGAO.LINK) != 0; isShared = (attr & ShellAPI.SFGAO.SHARE) != 0; isFileSystem = (attr & ShellAPI.SFGAO.FILESYSTEM) != 0; isHidden = (attr & ShellAPI.SFGAO.HIDDEN) != 0; hasSubFolder = false; isExplorable = false; canRename = (attr & ShellAPI.SFGAO.CANRENAME) != 0; canRead = (attr & ShellAPI.SFGAO.STREAM) != 0; isDisk = false; }
public static string GetDisplayName(DirectoryInfoEx dx) { IntPtr pidl; uint pchEaten = 0; var sfgao = new ShellAPI.SFGAO(); DirectoryInfoEx.DesktopDirectory.ShellFolder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, dx.FullName, ref pchEaten, out pidl, ref sfgao); var ptrStr = Marshal.AllocCoTaskMem(ShellAPI.MAX_PATH * 2 + 4); Marshal.WriteInt32(ptrStr, 0, 0); var buf = new StringBuilder(ShellAPI.MAX_PATH); try { DirectoryInfoEx.DesktopDirectory.ShellFolder.GetDisplayNameOf(pidl, ShellAPI.SHGNO.NORMAL, ptrStr); ShellAPI.StrRetToBuf(ptrStr, pidl, buf, ShellAPI.MAX_PATH); } finally { if (ptrStr != IntPtr.Zero) Marshal.FreeCoTaskMem(ptrStr); ptrStr = IntPtr.Zero; } return buf.ToString(); }
/// <summary> /// Sets the attributes of a folder ShellItem. /// </summary> private void SetFolderAttributes() { // folder attributes to retrieve with GetAttributesOf ShellAPI.SFGAO attr = ShellAPI.SFGAO.SHARE | ShellAPI.SFGAO.FILESYSTEM | ShellAPI.SFGAO.HIDDEN | ShellAPI.SFGAO.HASSUBFOLDER | ShellAPI.SFGAO.BROWSABLE | ShellAPI.SFGAO.CANRENAME | ShellAPI.SFGAO.STORAGE; parent.folder.GetAttributesOf(1, new IntPtr[] { relPidl.Ptr }, ref attr); isFolder = true; isLink = false; isShared = (attr & ShellAPI.SFGAO.SHARE) != 0; isFileSystem = (attr & ShellAPI.SFGAO.FILESYSTEM) != 0; isHidden = (attr & ShellAPI.SFGAO.HIDDEN) != 0; hasSubFolder = (attr & ShellAPI.SFGAO.HASSUBFOLDER) != 0; isExplorable = (attr & ShellAPI.SFGAO.BROWSABLE) != 0; canRename = (attr & ShellAPI.SFGAO.CANRENAME) != 0; canRead = (attr & ShellAPI.SFGAO.STORAGE) != 0; isDisk = (path.Length == 4) && (path.EndsWith(":\\")); }
public int GetAttributesOf(uint cidl, IntPtr[] apidl, ref ShellAPI.SFGAO rgfInOut) { checkDisposed(); return(_iShellFolder2.GetAttributesOf(cidl, apidl, ref rgfInOut)); }
public int ParseDisplayName(IntPtr hwnd, IntPtr pbc, string pszDisplayName, ref uint pchEaten, out IntPtr ppidl, ref ShellAPI.SFGAO pdwAttributes) { checkDisposed(); return(_iShellFolder2.ParseDisplayName(hwnd, pbc, pszDisplayName, ref pchEaten, out ppidl, ref pdwAttributes)); }
/// <summary> /// Selects a path from a value from the SpecialFolders enumeration. /// </summary> /// <param name="specialFolder">The SpecialFolder to select</param> /// <returns>The TreeNode of the directory which was selected, this will be null if the directory /// doesn't exist</returns> public TreeNode SelectPath(SpecialFolders specialFolder, bool expandNode) { StringBuilder path = new StringBuilder(256); IntPtr pidl = IntPtr.Zero; if (specialFolder == SpecialFolders.Desktop) { return(SelectPath("Desktop", expandNode)); } else if (ShellAPI.SHGetFolderPath( IntPtr.Zero, (ShellAPI.CSIDL)specialFolder, IntPtr.Zero, ShellAPI.SHGFP.TYPE_CURRENT, path) == ShellAPI.S_OK) { path.Replace(ShellBrowser.MyDocumentsPath, ShellBrowser.MyDocumentsName); return(SelectPath(path.ToString(), expandNode)); } else { #region Get Pidl if (specialFolder == SpecialFolders.MyDocuments) { uint pchEaten = 0; ShellAPI.SFGAO pdwAttributes = 0; ShellBrowser.DesktopItem.ShellFolder.ParseDisplayName( IntPtr.Zero, IntPtr.Zero, "::{450d8fba-ad25-11d0-98a8-0800361b1103}", ref pchEaten, out pidl, ref pdwAttributes); } else { ShellAPI.SHGetSpecialFolderLocation( IntPtr.Zero, (ShellAPI.CSIDL)specialFolder, out pidl); } #endregion #region Make Path if (pidl != IntPtr.Zero) { IntPtr strr = Marshal.AllocCoTaskMem(ShellAPI.MAX_PATH * 2 + 4); Marshal.WriteInt32(strr, 0, 0); StringBuilder buf = new StringBuilder(ShellAPI.MAX_PATH); if (ShellBrowser.DesktopItem.ShellFolder.GetDisplayNameOf( pidl, ShellAPI.SHGNO.FORADDRESSBAR | ShellAPI.SHGNO.FORPARSING, strr) == ShellAPI.S_OK) { ShellAPI.StrRetToBuf(strr, pidl, buf, ShellAPI.MAX_PATH); } Marshal.FreeCoTaskMem(pidl); Marshal.FreeCoTaskMem(strr); if (!string.IsNullOrEmpty(buf.ToString())) { return(SelectPath(buf.ToString(), expandNode)); } else { return(null); } } else { return(null); } #endregion } }
//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); } } }
public static bool IsZip(ShellAPI.SFGAO attribs) { return((attribs & ShellAPI.SFGAO.FOLDER) != 0 && (attribs & ShellAPI.SFGAO.STREAM) != 0); }
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); } } }