Directory.Delete(path, true) throws IOException The directory is not empty
It appears that info.EnumerateFiles
was the issue. I got that idea from this answer.
I switched that to info.GetFiles
and I was then able to delete the directory after.
How to delete the non empty directory in treeview using c#
The Directory.Delete method takes an optional second boolean parameter which indicates if you want to delete its contents. Just add true
as the second parameter:
System.IO.Directory.Delete(TreeView1.SelectedNode.FullPath, true);
Directory.Delete(path,true) delete all the files and subdirectories but throw an exception
Try using .NET Transactional File Manager
TxFileManager fileMgr = new TxFileManager();
using (TransactionScope scope1 = new TransactionScope())
{
fileMgr.DeleteDirectory(path);
scope1.Complete();
}
After Directory.Delete the Directory.Exists returning true sometimes?
Directory.Delete
calls the Windows API function RemoveDirectory
. The observed behavior is documented:
The
RemoveDirectory
function marks a directory for deletion on close. Therefore, the directory is not removed until the last handle to the directory is closed.
The .NET documentation is unfortunately missing this information. Whether the static Directory.Delete
method opens a handle to the directory is not documented. Likewise, if it does, it is not documented when the handle is closed.
Without any of this information, the best you can do is to poll for completion:
Directory.Delete(tempFolder, true);
while (Directory.Exists(tempFolder)) Thread.Sleep(0);
// At this point the directory has been removed from the filesystem
Even though polling should generally be avoided in preference of events, installing a filesystem watcher would be a bit over the top for this. Still, keep in mind, that this operation does not come for free, particularly when dealing with a network drive.
Update: With .NET's Reference Source available, the implementation of Directory.Delete can be inspected. The first action of this method is to iterate over all files and delete them. The iteration is implemented using FindFirstFile/FindNextFile. The returned handle is stored as a SafeFindHandle, a concrete subclass of SafeHandle. As the documentation points out, the native handle is freed through a concrete ReleaseHandle override. ReleaseHandle is called from a (postponed) critical finalizer. Since finalization is non-deterministic, this explains the open handle, responsible for the delayed directory delete.
This information, however, does not help in finding a better solution than the one described above (polling for completion).
Other answers to this question did not identify the core issue, and work by coincidence at best. BanksySan's answer adds unrelated code that introduces a delay to allow time for open handles to be closed. Byeni's answer is closer, yet still off: When he talks about the object referencing the directory he almost nails it. However, the object referencing the directory is called a handle, a native resource. Native resources are disposed of in finalizers, and
GC.Collect()
does not run finalizers. This, too, appears to work by buying extra time. Directory.Delete runs into IOException
I have solved the problem. Some (system) folders have Archive or ReadOnly flags. It seems the Directory.Delete (with recursive subfolder deletion) can't delete these folders. So you have to remove these attributes first.
Removing mehtod:
public static void ClearAttributes(string currentDir)
{
if (Directory.Exists(currentDir))
{
File.SetAttributes(currentDir, FileAttributes.Normal);
string[] subDirs = Directory.GetDirectories(currentDir);
foreach (string dir in subDirs)
{
ClearAttributes(dir);
}
string[] files = files = Directory.GetFiles(currentDir);
foreach (string file in files)
{
File.SetAttributes(file, FileAttributes.Normal);
}
}
}
Then, before Directory.Delete run this method.
ClearAttributes(serverShare + "\\" + user);
Directory.Delete(serverShare + "\\" + user, true);
So it works fine and all folders are deleted.
Related Topics
Windows Like Services Development in Linux Using Mono
Run Two Async Tasks in Parallel and Collect Results in .Net 4.5
Reading Email Using Pop3 in C#
How to Get the Unix Timestamp in C#
How to Pass Command-Line Arguments to a Winforms Application
How to Serialize a String as Cdata Using Xmlserializer
Parallel.Foreach VS Task.Factory.Startnew
Add New Item in Existing Array in C#.Net
Httpwebrequest Using Basic Authentication
Passing Properties by Reference in C#
Can You Develop Linux Applications with Xamarin
Why Doesn't .Net/C# Optimize for Tail-Call Recursion
Get a Screenshot of a Specific Application
Conditional Compilation and Framework Targets
How to Set Custom JSONserializersettings for JSON.Net in ASP.NET Web API
Specifying a Custom Datetime Format When Serializing with JSON.Net