Cannot delete directory with Directory.Delete(path

2019-01-01 03:17发布

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?

29条回答
无色无味的生活
2楼-- · 2019-01-01 03:44

This answer is based on: https://stackoverflow.com/a/1703799/184528. The difference with my code, is that we only recurse many delete sub-directories and files when necessary a call to Directory.Delete fails on a first attempt (which can happen because of windows explorer looking at a directory).

    public static void DeleteDirectory(string dir, bool secondAttempt = false)
    {
        // If this is a second try, we are going to manually 
        // delete the files and sub-directories. 
        if (secondAttempt)
        {
            // Interrupt the current thread to allow Explorer time to release a directory handle
            Thread.Sleep(0);

            // Delete any files in the directory 
            foreach (var f in Directory.GetFiles(dir, "*.*", SearchOption.TopDirectoryOnly))
                File.Delete(f);

            // Try manually recursing and deleting sub-directories 
            foreach (var d in Directory.GetDirectories(dir))
                DeleteDirectory(d);

            // Now we try to delete the current directory
            Directory.Delete(dir, false);
            return;
        }

        try
        {
            // First attempt: use the standard MSDN approach.
            // This will throw an exception a directory is open in explorer
            Directory.Delete(dir, true);
        }
        catch (IOException)
        {
            // Try again to delete the directory manually recursing. 
            DeleteDirectory(dir, true);
        }
        catch (UnauthorizedAccessException)
        {
            // Try again to delete the directory manually recursing. 
            DeleteDirectory(dir, true);
        } 
    }
查看更多
还给你的自由
3楼-- · 2019-01-01 03:44

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.

查看更多
泪湿衣
4楼-- · 2019-01-01 03:44

I think that there is a file open by some stream you are not aware of I had the same problem and solved it by closing all the streams that where pointing to the directory I wanted to delete.

查看更多
谁念西风独自凉
5楼-- · 2019-01-01 03:44

This error occurs if any file or directory is considered in-use. It is a misleading error. Check to see if you have any explorer windows or command-line windows open to any directory in the tree, or a program that is using a file in that tree.

查看更多
大哥的爱人
6楼-- · 2019-01-01 03:44

I´ve solved with this millenary technique (you can leave the Thread.Sleep on his own in the catch)

bool deleted = false;
        do
        {
            try
            {
                Directory.Delete(rutaFinal, true);                    
                deleted = true;
            }
            catch (Exception e)
            {
                string mensaje = e.Message;
                if( mensaje == "The directory is not empty.")
                Thread.Sleep(50);
            }
        } while (deleted == false);
查看更多
登录 后发表回答