我使用。net 3.5,试图递归删除目录使用:

Directory.Delete(myPath, true);

我的理解是,如果文件正在使用或存在权限问题,这应该抛出,但否则它应该删除目录及其所有内容。

然而,我偶尔会遇到这样的情况:

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)
    ...

我并不惊讶于这个方法有时会抛出错误,但我惊讶于当递归为真时得到这个特定的消息。(我知道目录不是空的。)

是否有一个原因,我将看到这个而不是AccessViolationException?


当前回答

如果您的应用程序(或任何其他应用程序)的当前目录是您试图删除的目录,这将不是访问冲突错误,而是目录不是空的。 通过更改当前目录,确保它不是您自己的应用程序;同时,确保该目录没有在其他程序中打开(例如Word, excel, Total Commander等)。大多数程序将cd到最后打开的文件的目录,这将导致这种情况。

其他回答

我今天遇到了这个问题。这是因为我有windows资源管理器打开目录,试图删除,导致递归调用失败,从而IOException。确保没有打开该目录的句柄。

此外,MSDN明确表示,您不必编写自己的回避:http://msdn.microsoft.com/en-us/library/fxeahc5f.aspx

我在特尔斐也遇到过同样的问题。最终的结果是我自己的应用程序锁定了我想要删除的目录。不知何故,当我写入目录(一些临时文件)时,目录被锁定了。

问题在于,在删除它之前,我对它的父目录做了一个简单的更改。

上面的答案对我都没用。似乎我自己的应用程序在目标目录上使用DirectoryInfo导致它保持锁定。

强制垃圾收集似乎解决了这个问题,但不是马上就能解决的。在需要的地方尝试删除几次。

注意目录。存在,因为它可以在异常后消失。我不知道为什么我的删除被延迟了(Windows 7 SP1)

        for (int attempts = 0; attempts < 10; attempts++)
        {
            try
            {
                if (Directory.Exists(folder))
                {
                    Directory.Delete(folder, true);
                }
                return;
            }
            catch (IOException e)
            {
                GC.Collect();
                Thread.Sleep(1000);
            }
        }

        throw new Exception("Failed to remove folder.");

我很惊讶没有人想到这个简单的非递归方法,它可以删除包含只读文件的目录,而不需要更改每个文件的只读属性。

Process.Start("cmd.exe", "/c " + @"rmdir /s/q C:\Test\TestDirectoryContainingReadOnlyFiles"); 

(稍微改变一下,暂时不启动cmd窗口,这在互联网上都是可用的)

这个答案基于:https://stackoverflow.com/a/1703799/184528。与我的代码不同的是,我们只递归许多删除子目录和文件时,需要调用目录。第一次尝试删除失败(这可能是因为windows资源管理器查看目录)。

    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);
        } 
    }