无法使用Directory.Delete删除目录(路径,true)

时间:2008-11-30 20:57:04

标签: c# .net exception io

我正在使用.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?

30 个答案:

答案 0 :(得分:219)

编者注:虽然这个答案包含一些有用的信息,但事实上Directory.Delete的工作方式不正确。请阅读此答案的评论以及此问题的其他答案。


之前我遇到过这个问题。

问题的根源是此函数不会删除目录结构中的文件。因此,您需要做的是创建一个函数,在删除目录本身之前删除目录结构中的所有文件,然后删除所有目录。我知道这与第二个参数相反,但它是一种更安全的方法。此外,您可能希望在删除文件之前从文件中删除READ-ONLY访问属性。否则会引发异常。

将此代码打到您的项目中。

public static void DeleteDirectory(string target_dir)
{
    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);
}

另外,对我来说,我个人在机器上允许删除的区域添加限制,因为您希望有人在C:\WINDOWS (%WinDir%)C:\上调用此功能。

答案 1 :(得分:169)

如果您尝试递归删除目录a并且目录a\b已在资源管理器中打开,b将被删除,但您将收到错误'目录不为空'的{ {1}}即使你去看看它是空的。任何应用程序的当前目录(包括资源管理器)retains a handle to the directory。当您致电a时,它会自下而上删除:Directory.Delete(true),然后b。如果在资源管理器中打开a,资源管理器将检测到b的删除,向上更改目录b并清理打开的句柄。由于文件系统异步操作,cd ..操作因与Explorer冲突而失败。

不完整的解决方案

我最初发布了以下解决方案,其中包含中断当前线程以允许Explorer时间释放目录句柄的想法。

Directory.Delete

但这仅在打开目录是要删除的目录的 immediate 子项时才有效。如果// incomplete! try { Directory.Delete(path, true); } catch (IOException) { Thread.Sleep(0); Directory.Delete(path, true); } 在资源管理器中已打开,并且您在a\b\c\d上使用此功能,则在删除ad后此技术将失败。

一个更好的解决方案

即使在资源管理器中打开了其中一个较低级别的目录,此方法也会处理深层目录结构的删除。

c

尽管我们自己进行了额外的递归工作,但我们仍然必须处理可能发生的/// <summary> /// Depth-first recursive delete, with handling for descendant /// directories open in Windows Explorer. /// </summary> public static void DeleteDirectory(string path) { foreach (string directory in Directory.GetDirectories(path)) { DeleteDirectory(directory); } try { Directory.Delete(path, true); } catch (IOException) { Directory.Delete(path, true); } catch (UnauthorizedAccessException) { Directory.Delete(path, true); } } 。目前尚不清楚第一次删除尝试是否为第二次成功删除尝试铺平了道路,或者它是否仅仅是抛出/捕获允许文件系统赶上的异常所引入的时间延迟。

您可以通过在UnauthorizedAccessException块的开头添加Thread.Sleep(0)来减少在典型条件下抛出和捕获的异常数。此外,存在一个风险,即在系统负载较重的情况下,您可以通过两次try次尝试并失败。将此解决方案视为更强大的递归删除的起点。

一般答案

此解决方案仅解决与Windows资源管理器交互的特性。如果你想要一个坚如磐石的删除操作,要记住的一点是,任何东西(病毒扫描程序,无论什么)都可以随时打开你想要删除的内容。所以你必须稍后再试。多久以后,您尝试多少次,取决于删除对象的重要性。作为MSDN indicates

  

强大的文件迭代代码必须考虑到许多复杂性   文件系统。

这个无辜的陈述,只提供了NTFS参考文档的链接,应该让你的头发站起来。

编辑:很多。这个答案最初只有第一个不完整的解决方案。)

答案 2 :(得分:40)

在进一步检查之前,请检查您控制的以下原因:

  • 文件夹是否设置为进程的当前目录?如果是,请先将其更改为其他内容。
  • 您是否从该文件夹中打开了文件(或加载了DLL)? (并忘了关闭/卸载它)

否则,请检查您无法控制的以下合法原因:

  • 该文件夹中有标记为只读的文件。
  • 您没有对其中某些文件的删除权限。
  • 文件或子文件夹在资源管理器或其他应用程序中打开。

如果出现以上任何问题,您应该在尝试改进删除代码之前了解其原因。 你的应用应该删除只读或无法访问的文件?是谁标记了他们,为什么?

一旦排除了上述原因,仍然存在虚假失败的可能性。如果任何人掌握任何要删除的文件或文件夹的句柄,删除将失败,并且有很多原因可能导致某人枚举该文件夹或读取其文件:

  • 搜索索引器
  • 抗病毒
  • 备份软件

处理虚假失败的一般方法是多次尝试,在尝试之间暂停。你显然不想永远尝试,所以你应该在经过一定次数的尝试后放弃并抛出异常或忽略错误。像这样:

private static void DeleteRecursivelyWithMagicDust(string destinationDir) {
    const int magicDust = 10;
    for (var gnomes = 1; gnomes <= magicDust; gnomes++) {
        try {
            Directory.Delete(destinationDir, true);
        } catch (DirectoryNotFoundException) {
            return;  // good!
        } catch (IOException) { // System.IO.IOException: The directory is not empty
            System.Diagnostics.Debug.WriteLine("Gnomes prevent deletion of {0}! Applying magic dust, attempt #{1}.", destinationDir, gnomes);

            // see http://stackoverflow.com/questions/329355/cannot-delete-directory-with-directory-deletepath-true for more magic
            Thread.Sleep(50);
            continue;
        }
        return;
    }
    // depending on your use case, consider throwing an exception here
}

在我看来,这样的帮助应该用于所有删除,因为虚假失败总是可能的。但是,您应该将此代码添加到您的使用案例中,而不是盲目地复制它。

我的应用程序生成的内部数据文件夹的虚假失败,位于%LocalAppData%下,所以我的分析是这样的:

  1. 该文件夹仅由我的应用程序控制,并且用户没有正当理由将该文件夹中的内容标记为只读或无法访问,因此我不会尝试处理该情况。

  2. 那里没有有价值的用户创建的东西,因此不存在强行删除错误内容的风险。

  3. 作为一个内部数据文件夹,我不希望它在资源管理器中打开,至少我觉得不需要专门处理这种情况(即我通过支持处理这种情况很好)

  4. 如果所有尝试都失败,我会选择忽略该错误。最糟糕的情况是,该应用程序无法解压缩一些较新的资源,崩溃并提示用户联系支持,只要不经常发生,我就可以接受。或者,如果应用程序没有崩溃,它会留下一些旧数据,这对我来说也是可以接受的。

  5. 我选择将重试次数限制为500毫秒(50 * 10)。这是一个在实践中起作用的任意门槛;我希望阈值足够短,以便用户不会杀死应用程序,认为它已经停止响应。另一方面,半秒钟是罪犯完成处理我的文件夹的充足时间。从其他有时甚至可以找到Sleep(0)的SO答案来判断,很少有用户会经历多次重试。

  6. 我每50ms重试一次,这是另一个任意数字。我觉得如果一个文件正在处理(索引,检查),当我尝试删除它时,50ms是在我的情况下期望完成处理的正确时间。此外,50ms足够小,不会导致明显的减速;再次,Sleep(0)在许多情况下似乎已经足够了,所以我们不想拖延太多。

  7. 代码重试任何IO异常。我通常不希望任何异常访问%LocalAppData%,因此我选择简单并接受500毫秒延迟的风险,以防发生合法异常。我也不想找到一种方法来检测我想要重试的确切异常。

答案 3 :(得分:15)

应该提到的一件重要的事情(我将其添加为注释但我不允许)是重载的行为从.NET 3.5更改为.NET 4.0。

Directory.Delete(myPath, true);

从.NET 4.0开始,它删除文件夹本身的文件,但不删除3.5。这也可以在MSDN文档中看到。

.NET 4.0

  

删除指定的目录,如果有指示,则删除目录中的所有子目录和文件。

.NET 3.5

  

删除空目录,如果有指示,则删除目录中的所有子目录和文件。

答案 4 :(得分:13)

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

问题22是,我在删除它之前向它的父母做了一个简单的更改目录

答案 5 :(得分:11)

现代异步回答

接受的答案是完全错误的,它可能适用于某些人,因为从磁盘获取文件所花费的时间可以解除锁定文件的任何问题。事实是,这是因为文件被某些其他进程/流/操作锁定。其他答案使用Thread.Sleep(Yuck)在一段时间后重试删除目录。这个问题需要重新审视一个更现代的答案。

public static async Task<bool> TryDeleteDirectory(
   string directoryPath,
   int maxRetries = 10,
   int millisecondsDelay = 30)
{
    if (directoryPath == null)
        throw new ArgumentNullException(directoryPath);
    if (maxRetries < 1)
        throw new ArgumentOutOfRangeException(nameof(maxRetries));
    if (millisecondsDelay < 1)
        throw new ArgumentOutOfRangeException(nameof(millisecondsDelay));

    for (int i = 0; i < maxRetries; ++i)
    {
        try
        {
            if (Directory.Exists(directoryPath))
            {
                Directory.Delete(directoryPath, true);
            }

            return true;
        }
        catch (IOException)
        {
            await Task.Delay(millisecondsDelay);
        }
        catch (UnauthorizedAccessException)
        {
            await Task.Delay(millisecondsDelay);
        }
    }

    return false;
}

单元测试

这些测试显示了锁定文件如何导致Directory.Delete失败以及上述TryDeleteDirectory方法如何解决问题的示例。

[Fact]
public async Task TryDeleteDirectory_FileLocked_DirectoryNotDeletedReturnsFalse()
{
    var directoryPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
    var subDirectoryPath = Path.Combine(Path.GetTempPath(), "SubDirectory");
    var filePath = Path.Combine(directoryPath, "File.txt");

    try
    {
        Directory.CreateDirectory(directoryPath);
        Directory.CreateDirectory(subDirectoryPath);

        using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write))
        {
            var result = await TryDeleteDirectory(directoryPath, 3, 30);
            Assert.False(result);
            Assert.True(Directory.Exists(directoryPath));
        }
    }
    finally
    {
        if (Directory.Exists(directoryPath))
        {
            Directory.Delete(directoryPath, true);
        }
    }
}

[Fact]
public async Task TryDeleteDirectory_FileLockedThenReleased_DirectoryDeletedReturnsTrue()
{
    var directoryPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
    var subDirectoryPath = Path.Combine(Path.GetTempPath(), "SubDirectory");
    var filePath = Path.Combine(directoryPath, "File.txt");

    try
    {
        Directory.CreateDirectory(directoryPath);
        Directory.CreateDirectory(subDirectoryPath);

        Task<bool> task;
        using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write))
        {
            task = TryDeleteDirectory(directoryPath, 3, 30);
            await Task.Delay(30);
            Assert.True(Directory.Exists(directoryPath));
        }

        var result = await task;
        Assert.True(result);
        Assert.False(Directory.Exists(directoryPath));
    }
    finally
    {
        if (Directory.Exists(directoryPath))
        {
            Directory.Delete(directoryPath, true);
        }
    }
}

答案 6 :(得分:11)

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

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

(稍微更改一下,不要暂时触发cmd窗口,这可以在互联网上找到)

答案 7 :(得分:10)

您可以通过运行以下来重现错误:

Directory.CreateDirectory(@"C:\Temp\a\b\c\");
Process.Start(@"C:\Temp\a\b\c\");
Thread.Sleep(1000);
Directory.Delete(@"C:\Temp\a\b\c");
Directory.Delete(@"C:\Temp\a\b");
Directory.Delete(@"C:\Temp\a");

尝试删除目录'b'时,会抛出IOException“目录不为空”。这是愚蠢的,因为我们刚刚删除了目录'c'。

根据我的理解,解释是目录'c'标记为已删除。但删除尚未在系统中提交。系统已完成作业的回复,而实际上它仍在处理中。系统可能正在等待文件资源管理器将焦点放在父目录上以提交删除。

如果您查看删除功能(http://referencesource.microsoft.com/#mscorlib/system/io/directory.cs)的源代码,您将看到它使用本机Win32Native.RemoveDirectory函数。这里记录了这种等待行为:

  

RemoveDirectory函数在关闭时标记要删除的目录。因此,在关闭目录的最后一个句柄之前,不会删除该目录。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa365488(v=vs.85).aspx

睡眠和重试是解决方案。请参阅ryascl的解决方案。

答案 8 :(得分:7)

我有一个奇怪的权限问题,删除用户配置文件目录(在C:\ Documents and Settings中),尽管能够在Explorer shell中这样做。

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

对我来说,“文件”操作对目录的作用没有意义,但我知道它有效,对我来说已经足够了!

答案 9 :(得分:3)

此答案基于:https://stackoverflow.com/a/1703799/184528。与我的代码的不同之处在于,我们只会在必要时对许多删除子目录和文件进行递归,以便在第一次尝试时对Directory.Delete的调用失败(这可能因为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);
        } 
    }

答案 10 :(得分:2)

以上解决方案对我来说效果不错。最后我使用了@ryascl解决方案的编辑版本,如下所示:

    /// <summary>
    /// Depth-first recursive delete, with handling for descendant 
    /// directories open in Windows Explorer.
    /// </summary>
    public static void DeleteDirectory(string path)
    {
        foreach (string directory in Directory.GetDirectories(path))
        {
            Thread.Sleep(1);
            DeleteDir(directory);
        }
        DeleteDir(path);
    }

    private static void DeleteDir(string dir)
    {
        try
        {
            Thread.Sleep(1);
            Directory.Delete(dir, true);
        }
        catch (IOException)
        {
            DeleteDir(dir);
        }
        catch (UnauthorizedAccessException)
        {
            DeleteDir(dir);
        }
    }

答案 11 :(得分:2)

我花了几个小时来解决这个问题以及删除目录的其他异常。 这是我的解决方案

 public static void DeleteDirectory(string target_dir)
    {
        DeleteDirectoryFiles(target_dir);
        while (Directory.Exists(target_dir))
        {
            lock (_lock)
            {
                DeleteDirectoryDirs(target_dir);
            }
        }
    }

    private static void DeleteDirectoryDirs(string target_dir)
    {
        System.Threading.Thread.Sleep(100);

        if (Directory.Exists(target_dir))
        {

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

            if (dirs.Length == 0)
                Directory.Delete(target_dir, false);
            else
                foreach (string dir in dirs)
                    DeleteDirectoryDirs(dir);
        }
    }

    private static void DeleteDirectoryFiles(string target_dir)
    {
        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)
        {
            DeleteDirectoryFiles(dir);
        }
    }

此代码具有较小的延迟,这对我的应用程序并不重要。但要小心,如果您要删除的目录中有很多子目录,则延迟可能会成为问题。

答案 12 :(得分:2)

不删除文件的递归目录删除肯定是意外的。我对此的解决方法:

public class IOUtils
{
    public static void DeleteDirectory(string directory)
    {
        Directory.GetFiles(directory, "*", SearchOption.AllDirectories).ForEach(File.Delete);
        Directory.Delete(directory, true);
    }
}

我遇到过这种情况有帮助的情况,但一般来说,Directory.Delete会在递归删除时删除目录中的文件,如documented in msdn

我不时会遇到这种不正常的行为,也是Windows资源管理器的用户:有时我无法删除文件夹(它认为荒谬的消息是“访问被拒绝”)但是当我向下钻取并删除较低的项目时我可以删除上面的项目。所以我猜上面的代码处理操作系统异常 - 而不是基类库问题。

答案 13 :(得分:1)

是否可能存在竞争条件,其他线程或进程正在向目录添加文件:

序列如下:

删除程序A:

  1. 清空目录
  2. 删除(现在为空)目录。
  3. 如果其他人在1&amp;之间添加了一个文件2,那么也许2会抛出列出的异常?

答案 14 :(得分:1)

当路径长度大于260个符号的目录(或任何子目录)中存在文件时,Windows上可能会出现此问题。

在这种情况下,您需要删除<?php $f1 = file_get_contents("exam1.xml"); $f2 = file_get_contents("exam2.xml"); $response = array('files' => array($f1, $f2)); echo json_encode($response); ?> 而不是\\\\?\C:\mydir。 关于260个符号限制,您可以阅读here

答案 15 :(得分:1)

如上所述&#34;接受&#34;解决方案在重新分析点上失败了 - 但人们仍然将其标记出来(???)。有一个更短的解决方案可以正确复制功能:

public static void rmdir(string target, bool recursive)
{
    string tfilename = Path.GetDirectoryName(target) +
        (target.Contains(Path.DirectorySeparatorChar.ToString()) ? Path.DirectorySeparatorChar.ToString() : string.Empty) +
        Path.GetRandomFileName();
    Directory.Move(target, tfilename);
    Directory.Delete(tfilename, recursive);
}

我知道,并不处理后面提到的权限案例,但是出于所有意图和目的,FAR BETTER提供了原始/库存Directory.Delete()预期功能 - 而且代码也少得多

你可以安全地继续进行处理,因为旧的目录将不会出现 ...即使没有消失,因为“文件系统仍在追赶”。 (或者MS提供破损功能的任何借口)

作为一项好处,如果您知道您的目标目录很大/很深并且不想等待(或打扰例外),那么最后一行可以替换为:

    ThreadPool.QueueUserWorkItem((o) => { Directory.Delete(tfilename, recursive); });

继续工作仍然是安全的。

答案 16 :(得分:1)

这是因为 FileChangesNotifications.

它发生在ASP.NET 2.0之后。当您删除应用内的某个文件夹时,会重新启动。你可以自己看看,使用 ASP.NET Health Monitoring

只需将此代码添加到您的web.config / configuration / system.web:

<healthMonitoring enabled="true">
  <rules>
    <add name="MyAppLogEvents" eventName="Application Lifetime Events" provider="EventLogProvider" profile="Critical"/>
  </rules>
</healthMonitoring>


之后退房Windows Log -> Application。 到底是怎么回事:

删除文件夹时,如果有任何子文件夹,Delete(path, true)会先删除子文件夹。 FileChangesMonitor足以了解删除和关闭您的应用程序。同时您的主目录尚未删除。这是Log:

中的事件


enter image description here


Delete()没有完成其工作,因为应用程序正在关闭,它引发了一个异常:

enter image description here

如果在您要删除的文件夹中没有任何子文件夹,则删除()只删除所有文件和该文件夹,应用程序也会重新启动,但您不要得到任何异常,因为app restart不会中断任何事情。但是,您仍然会丢失所有进程内会话,应用程序在重新启动时不响应请求等等。

现在怎么办?

有一些解决方法和调整可以禁用此行为,Directory JunctionTurning Off FCN with RegistryStopping FileChangesMonitor using Reflection (since there is no exposed method),但它们似乎都不正确,因为FCN是有原因的。它正在关注您应用的结构,它不是数据结构。简短的回答是:在应用程序之外放置要删除的文件夹。 FileChangesMonitor将不会收到任何通知,并且您的应用每次都不会重新启动。你不会有例外。要从网上看到它们,有两种方法:

  1. 创建一个处理传入呼叫的​​控制器,然后通过从应用程序外部的文件夹(wwwroot外部)读取文件。

  2. 如果您的项目很大并且性能最重要,请设置单独的小型和快速Web服务器来提供静态内容。因此,您将离开IIS到他的具体工作。它可以在同一台机器上(用于Windows的mongoose)或另一台机器(用于Linux的nginx)。好消息是你不必支付额外的微软许可证来在linux上设置静态内容服务器。

  3. 希望这有帮助。

答案 17 :(得分:1)

我在使用TFS2012的构建服务器上遇到了与Windows Workflow Foundation相同的问题。在内部,名为Directory.Delete()的工作流将递归标志设置为true。在我们的案例中,它似乎与网络相关。

我们正在删除网络共享上的二进制drop文件夹,然后重新创建并使用最新的二进制文件重新填充它。其他每个构建都会失败。在构建失败后打开drop文件夹时,该文件夹为空,这表示Directory.Delete()调用的每个方面都成功,除了删除实际目录。

问题似乎是由网络文件通信的异步性质引起的。构建服务器告诉文件服务器删除所有文件和文件服务器报告它已经有,即使它没有完全完成。然后构建服务器请求删除目录,文件服务器拒绝该请求,因为它没有完全删除文件。

在我们的案例中有两种可能的解决方案:

  • 在我们自己的代码中建立递归删除,并在每个步骤之间进行延迟和验证
  • 在IOException之后重试最多X次,在再次尝试之前给出延迟

后一种方法既快又脏,但似乎可以解决问题。

答案 18 :(得分:1)

我今天遇到了这个问题。之所以发生这种情况,是因为我将Windows资源管理器打开到试图删除的目录,导致递归调用失败,从而导致IOException。确保目录中没有句柄。

此外,MSDN很清楚您不必写自己的错觉:http://msdn.microsoft.com/en-us/library/fxeahc5f.aspx

答案 19 :(得分:1)

在Windows资源管理器中选择路径或子文件夹似乎足以阻止Directory.Delete(path,true)的单次执行,如上所述抛出IOException并死亡而不是将Windows资源管理器引导到父文件夹和预期的程序。

答案 20 :(得分:1)

目录或其中的文件已被锁定,无法删除。找到锁定它的罪魁祸首,看看你是否可以消除它。

答案 21 :(得分:0)

如果考虑使用任何文件或目录,则会发生此错误。这是一个误导性的错误。检查是否有任何资源管理器窗口或命令行窗口打开到树中的任何目录,或者是在该树中使用文件的程序。

答案 22 :(得分:0)

我认为某个流打开了一个文件你不知道我遇到了同样的问题,并通过关闭所有指向我想要删除的目录的流来解决它。

答案 23 :(得分:0)

当方法异步并且编码如下时,我解决了所述问题的一个可能实例:

// delete any existing update content folder for this update
if (await fileHelper.DirectoryExistsAsync(currentUpdateFolderPath))
       await fileHelper.DeleteDirectoryAsync(currentUpdateFolderPath);

有了这个:

bool exists = false;                
if (await fileHelper.DirectoryExistsAsync(currentUpdateFolderPath))
    exists = true;

// delete any existing update content folder for this update
if (exists)
    await fileHelper.DeleteDirectoryAsync(currentUpdateFolderPath);

结论?有一些异步的方面是摆脱用于检查微软无法说话的存在的句柄。就好像if语句中的异步方法的if语句就像using语句一样。

答案 24 :(得分:0)

如果是网络文件,Directory.DeleteHelper(recursive:= true)可能会导致因删除文件延迟而导致的IOException

答案 25 :(得分:0)

如果您的应用程序(或任何其他应用程序)的当前目录是您尝试删除的目录,则它不会是访问冲突错误,但目录不为空。 通过更改当前目录确保它不是您自己的应用程序;此外,请确保该目录未在某些其他程序中打开(例如Word,Excel,Total Commander等)。大多数程序将cd到最后打开的文件的目录,这将导致该目录。

答案 26 :(得分:0)

我已经采用了这种千禧技术解决了问题(您可以将Thread.Sleep留在自己的手上)

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

答案 27 :(得分:0)

您不必创建递归的额外方法或删除文件夹Extra中的文件。这一切都通过调用

自动完成
  

DirectoryInfo.Delete();

详细信息为here

类似的东西效果很好:

  var directoryInfo = new DirectoryInfo("My directory path");
    // Delete all files from app data directory.

    foreach (var subDirectory in directoryInfo.GetDirectories())
    {
          subDirectory.Delete(true);// true set recursive paramter, when it is true delete sub file and sub folder with files too
    }

将true用作变量来删除方法,也会删除子文件和包含文件的子文件夹。

答案 28 :(得分:-2)

上述答案都不适合我。我的应用程序在目标目录上使用DirectoryInfo似乎导致它保持锁定状态。

强制垃圾收集似乎解决了这个问题,但不是马上解决。一些尝试删除所需的地方。

请注意Directory.Exists,因为它可能会在异常后消失。我不知道为什么删除对我的延迟(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.");

答案 29 :(得分:-3)

在第二个参数中添加true。

Directory.Delete(path, true);

它将删除所有。