views:

7595

answers:

10

I'm using .NET 3.5, trying to recursively delete a directory using:

Directory.Delete(myPath, true);

My understanding is that this should throw if files are in use or there is a permissions problem, but otherwise it should delete the directory and all of its contents.

However, I occasionally get this:

System.IO.IOException: The directory is not empty.
    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
    at System.IO.Directory.DeleteHelper(String fullPath, String userPath, Boolean recursive)
    at System.IO.Directory.Delete(String fullPath, String userPath, Boolean recursive)
    ...

I'm not surprised that the method sometimes throws, but I'm surprised to get this particular message when recursive is true. (I know the directory is not empty.)

Is there a reason I'd see this instead of AccessViolationException?

+1  A: 

I had the very same problem under Delphi. And the end result was that my own application was locking the directory I wanted to delete. Somehow the directory got locked when I was writing to it (some temporary files).

The catch 22 was, I made a simple change directory to it's parent before deleting it.

Drejc
A: 

Is it possible you have a race condition where another thread or process is adding files to the directory:

The sequence would be:

Deleter process A:

  1. Empty the directory
  2. Delete the (now empty) directory.

If someone else adds a file between 1 & 2, then maybe 2 would throw the exception listed?

Douglas Leeder
A: 

The directory or a file in it is locked and cannot be deleted. Find the culprit who locks it and see if you can eliminate it.

Vilx-
+14  A: 

I ran into this problem before.

The root of the problem is that this function does not delete files that are within the directory structure. So what you'll need to do is create a function that deletes all the files within the directory structure then all the directories before removing the directory itself. I know this goes against the second parameter but it's a much safer approach. In addition, you will probably want to remove READ-ONLY access attributes from the files right before you delete them. Otherwise that will raise an exception.

Just slap this code into your project.

    public static bool DeleteDirectory(string target_dir)
    {
        bool result = false;

        string[] files = Directory.GetFiles(target_dir);
        string[] dirs = Directory.GetDirectories(target_dir);

        foreach (string file in files)
        {
            File.SetAttributes(file, FileAttributes.Normal);
            File.Delete(file);
        }

        foreach (string dir in dirs)
        {
            DeleteDirectory(dir);
        }

        Directory.Delete(target_dir, false);

        return result;
    }

Also, for me I personally add a restriction on areas of the machine that are allowed to be deleted because do you want someone to call this function on C:\WINDOWS (%WinDir%) or C:.

Jeremy Edwards
Seriously? Seems like a no-brainer .NET extension. Why would the framework designers choose to omit this?
Mike Caron
Thanks by the way, this was a helpful copy/paste.
Mike Caron
This is non sense. Directory.Delete(myPath, true) is an overload that delete all files that are within the directory structure. If you wanna get wrong, get wrong with Ryan S answer.
Sig. Tolleranza
In the above code - result is always false, is there a reason for that?
JL
I had the same excpetion, and it does seem lije Ryan S. naswer's is more ligely to be related with the problem.
Paulo Manuel Santos
Ryan S. answer +1
Ybbest
+1 because although Directory.Delete() does delete files inside its subdirectories (with recursive = true), it throws an "IOException : Directory is not empty" if one of the sub-directories or files is read-only. So this solution works better than Directory.Delete()
Anthony Brien
We have a product deployed on many different environments. Recently I had another one of these exceptions on a different module. I can see that there are no read-only files on the directory. Again I point to Ryan S. solution.
Paulo Manuel Santos
A: 

If your application's (or any other application's) current directory is the one you're trying to delete, it will not be an access violation error but a directory is not empty. Make sure it's not your own application by changing the current directory; also, make sure the directory is not open in some other program (e.g. Word, excel, Total Commander, etc.). Most programs will cd to the directory of the last file opened, which would cause that.

configurator
A: 

This happened to me when I was changing attributes on files in the directory, then deleting the directory. (I was changing the files not to be read-only so they'd be deleted.)

I got around it this way:

while (Directory.Exists(dir))
{
    try
    {
        Directory.Delete(dir, true);
    }
    catch(IOException) { }
}

As long as it's only a temporary lock caused by your own program, this seems to work OK. If you think the cause is some other program, you might want to include some code to set a timeout period.

Kyralessa
A: 

Thanks Jeremy Edwards for your help!

I had a those weird permission problems deleting User Profile directories (in C:\Documents and Settings) despite being able to do so in the Explorer shell.

The code you give works, but I had to add an additional line:

File.SetAttributes(target_dir, FileAttributes.Normal);
Directory.Delete(target_dir, false);

It makes no sense to me what a "file" operation does on a directory, but I know that it works and that's enough for me!

+7  A: 

If you are getting IOException deleting directories that are open in Explorer, add a sleep(0) to give Explorer a chance to release the directory handle.

try
{
    Directory.Delete( path, false );
}
catch ( IOException )
{
    Thread.Sleep( 0 );
    Directory.Delete( path, false );
}
Ryan S
It does appear calling Directory.Delete(path, true) while path or one of the folders/files under path is open or selected in Windows Explorer will throw an IOException. Closing Windows Explorer and rerunning my existing code w/o the try/catch suggested above worked fine.
David Alpert
I think this may happen even if explorer is not open on the directory. I think it can be related with anti-virus accessing it. In my case the machine had Norton.
Paulo Manuel Santos
A: 

It appears that having the path or subfolder selected in Windows Explorer is enough to block a single execution of Directory.Delete(path, true), throwing an IOException as described above and dying instead of booting Windows Explorer out to a parent folder and proceding as expected.

David Alpert
A: 

I don't get it either. It seems the code in the example always returns false. Is there a reason for it?

Ozymades