private static bool DeleteDirectoryTree(ref Win32.WIN32_FIND_DATA fd, string dir, StringBuilder sb) { IntPtr hFind = NativeMethods.FindFirstFile(Path.Combine(dir, "*"), out fd); if (hFind == NativeMethods.INVALID_HANDLE_VALUE) { return(false); } do { if (fd.cFileName == "." || fd.cFileName == "..") { continue; //pseudo-directory } string path = Path.Combine(dir, fd.cFileName); if ((fd.dwFileAttributes & FileAttributes.ReadOnly) != 0) { NativeMethods.SetFileAttributes(path, fd.dwFileAttributes & ~FileAttributes.ReadOnly); } if ((fd.dwFileAttributes & FileAttributes.Directory) != 0) { DeleteDirectoryTree(ref fd, path, sb); NativeMethods.RemoveDirectory(path); continue; } if (!NativeMethods.DeleteFile(path) && sb != null) { sb.AppendFormat("{0} : {1}\r\n", path, Win32Exception.GetLastErrorMessage()); } } while (NativeMethods.FindNextFile(hFind, out fd)); NativeMethods.FindClose(hFind); return(NativeMethods.RemoveDirectory(dir)); }
/// <summary> /// Delete entire directory tree including all files. Even read-only ones. /// NO exceptions will be thrown. /// </summary> /// <param name="dir">Directory tree to be deleted.</param> /// <param name="sb">Optional. Contains a list of files (with error msg) that could not be deleted.</param> /// <returns>True if successful, if false, 'sb' contains the files that could not be deleted.</returns> public static bool DeleteDirectoryTree(string dir, StringBuilder sb = null) { if (string.IsNullOrWhiteSpace(dir)) { if (sb != null) { sb.AppendFormat("Directory \"{0}\" not found.", dir ?? "null"); } return(false); } if (!Directory.Exists(dir)) { if (sb != null) { sb.AppendFormat("Directory \"{0}\" not found.", dir); } return(false); } Win32.WIN32_FIND_DATA fd = new Win32.WIN32_FIND_DATA(); //pass as ref (aka ptr) to avoid filling up the stack return(DeleteDirectoryTree(ref fd, dir, sb)); }