不能使用目录删除目录。删除(路径,真的)

我使用。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?

285496 次浏览

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

问题在于,在删除它之前,我给它的父对象做了一个简单的改变当前工作目录

你是否可能有一个竞争条件,另一个线程或进程正在向目录中添加文件:

顺序是:

删除进程A:

  1. 清空目录
  2. 删除(现在是空的)目录。

如果其他人在1 &2,那么2可能会抛出列出的异常?

目录或文件处于锁定状态,不能被删除。找到锁它的罪魁祸首,看看你是否能消除它。

虽然这个答案包含了一些有用的信息,但关于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:\上调用这个函数。

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

我有那些奇怪的权限问题删除用户配置文件目录(在C:\文档和设置),尽管能够这样做在资源管理器外壳。

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

对我来说,“文件”操作在目录上做什么毫无意义,但我知道它可以工作,这对我来说就足够了!

如果你试图递归删除目录a,而目录a\b在资源管理器中打开,b将被删除,但你会得到a的错误“目录不是空的”,即使当你去看的时候它是空的。任何应用程序(包括浏览器)的当前目录a\b1。当你调用Directory.Delete(true)时,它从下向上删除:b,然后a。如果在资源管理器中打开了b,资源管理器将检测到b的删除,向上改变目录cd ..并清理打开的句柄。由于文件系统是异步操作的,所以a\b0操作会因为与浏览器冲突而失败。

不完整的解决方案

我最初发布了以下解决方案,想法是中断当前线程,让资源管理器有时间释放目录句柄。

// incomplete!
try
{
Directory.Delete(path, true);
}
catch (IOException)
{
Thread.Sleep(0);
Directory.Delete(path, true);
}

但只有当打开的目录是你要删除的目录的立即子目录时,这才有效。如果在资源管理器中打开了a\b\c\d,并且你在a上使用它,则在删除dc后,此技术将失败。

一个更好的解决方案

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

/// <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。尚不清楚第一次删除尝试是否为第二次成功的删除尝试铺平了道路,或者仅仅是抛出/捕获异常导致的时间延迟,允许文件系统赶上。

通过在try块的开头添加Thread.Sleep(0),可以减少在典型条件下抛出和捕获的异常数量。此外,在系统负载较重的情况下,还存在这样的风险,即您可能会遍历两次Directory.Delete尝试并失败。可以将此解决方案作为更健壮的递归删除的起点。

一般的答案

此解决方案仅处理与Windows资源管理器交互的特性。如果你想要一个坚如磐石的删除操作,有一件事要记住,任何东西(病毒扫描程序,无论什么)都可能在任何时候对你试图删除的东西有一个开放的句柄。所以你得稍后再试。多久之后,以及尝试了多少次,取决于删除对象的重要性。MSDN表示,

健壮的文件迭代代码必须考虑到许多复杂性

这个无辜的声明,只提供了一个到NTFS参考文档的链接,应该会让你汗毛直竖。

(编辑:很多。这个答案原来只有第一个不完全解。)

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

对于网络文件,Directory.DeleteHelper(recursive:=true)可能会导致IOException,这是由于删除文件的延迟造成的

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

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

我已经花了几个小时来解决这个问题和删除目录的其他异常。 这就是解

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

这段代码有很小的延迟,这对我的应用程序并不重要。但是要注意,如果要删除的目录中有很多子目录,那么延迟可能会成为一个问题。

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

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

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

在继续之前,检查一下你能控制的以下原因:

  • 该文件夹是否设置为您的进程的当前目录?如果是,请先将其更改为其他内容。
  • 您是否从该文件夹中打开了文件(或加载了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. 我选择将重试次数限制在500ms(50 * 10)。这是一个在实践中起作用的任意阈值;我希望阈值足够短,这样用户就不会认为它已经停止响应而杀死应用程序。另一方面,半秒钟的时间足够罪犯处理完我的文件夹了。从其他SO答案判断,有时甚至Sleep(0)也是可以接受的,很少有用户会经历一次以上的重试。

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

  7. 代码对任何IO异常进行重试。我通常不希望有任何异常访问%LocalAppData%,所以我选择了简单性,并接受了在发生合法异常时500ms延迟的风险。我也不想找出一种方法来检测我想要重试的确切异常。

不删除文件的递归目录删除当然是意外的。我的解决办法是:

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

我经历过这样做有帮助的案例,但一般来说,Directory。Delete在递归删除时删除目录中的文件,如MSDN记录

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

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

在用最新的二进制文件重新创建和重新填充网络共享上的二进制文件之前,我们正在删除它。其他的构建都会失败。在构建失败后打开删除文件夹时,文件夹为空,这表明directory. delete()调用的每个方面都是成功的,除了删除实际的目录。

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

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

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

后一种方法又快又脏,但似乎很管用。

这是因为< >强FileChangesNotifications。< / >强

它发生在ASP。NET 2.0。当你删除应用程序中的某个文件夹时,它被重新启动。你可以自己看,用 < >强ASP。NET运行状况监视 . < / p >

只需将这段代码添加到你的web.config/configuration/system.web:

<healthMonitoring enabled="true">
<rules>
<add name="MyAppLogEvents" eventName="Application Lifetime Events" provider="EventLogProvider" profile="Critical"/>
</rules>
</healthMonitoring>
< p >
之后,检查Windows Log -> Application。 发生了什么:

< / p >

当你删除文件夹时,如果有子文件夹,Delete(path, true)会先删除子文件夹。这足以让FileChangesMonitor知道删除和关闭你的应用程序。同时你的主目录还没有删除。这是来自日志的事件:


enter image description here


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

< / p >

enter image description here

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

< em >现在什么?< / em >

有一些变通方法和调整来禁用这种行为,的目录结使用注册表关闭FCN使用反射停止FileChangesMonitor(因为没有公开的方法),但它们似乎都不正确,因为FCN的存在是有原因的。它在寻找应用的结构,而不是数据结构。简单的回答是:把你想要删除的文件夹放在你的应用程序之外。FileChangesMonitor不会收到任何通知,你的应用程序也不会每次都重新启动。你不会得到任何例外。要让它们在网上可见,有两种方法:

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

  2. 如果你的项目很大,性能是最重要的,那就单独设置一个小型快速的web服务器来提供静态内容。因此,您将把他的具体工作留给IIS。它可以在同一台机器上(Windows的mongoose),也可以在另一台机器上(Linux的nginx)。好消息是你不需要支付额外的微软许可证来在linux上设置静态内容服务器。

希望这能有所帮助。

上面的答案对我都没用。似乎我自己的应用程序在目标目录上使用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.");

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

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'被标记为已删除。但是系统中还没有提交删除操作。系统已经回复任务已经完成,而实际上它还在处理中。系统可能会等待文件资源管理器已经关注到父目录才提交删除。

如果你查看Delete函数(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的溶液。

如上所述,“accept "解决方案在重解析点上失败。 有一个更短的解决方案可以正确地复制功能:

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提供了原始/stock Directory.Delete() ——而且代码也少了很多预期的功能

你可以安全地继续处理,因为旧的目录将被排除在...即使没有消失,因为“文件系统仍在追赶”(或任何借口,微软提供了一个坏的功能)中。

作为一个好处,如果你知道你的目标目录是大/深的,并且不想等待(或麻烦的异常),最后一行可以替换为:

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

你仍然可以安全地继续工作。

这个答案基于: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);
}
}

当方法是异步的并像这样编码时,我解决了上述问题的一个可能实例:

// 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语句一样。

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

在这种情况下,你需要删除\\\\?\C:\mydir而不是C:\mydir。 关于260个符号的限制,您可以阅读在这里

有一件重要的事情需要提一下(我把它作为注释添加了进去,但是不允许我这样做),那就是重载的行为从。net 3.5改变到了。net 4.0。

Directory.Delete(myPath, true);

从。net 4.0开始,它会删除文件夹中的文件,但在3.5中不会。在MSDN文档中也可以看到这一点。

net 4.0

删除指定目录,如果指定,删除目录中的任何子目录和文件。

net 3.5

删除空目录,如果指定,删除目录中的任何子目录和文件。

现代异步回答

公认的答案是完全错误的,它可能适用于某些人,因为从磁盘获取文件所花费的时间释放了锁定文件的任何东西。事实上,这是因为文件被其他进程/流/操作锁定了。其他答案使用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);
}
}
}

以上的解决方案都不适合我。我最终使用了一个编辑版本的@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);
}
}

我已经解决了这个千年技术(你可以离开线程。睡在自己的捕捉)

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

你不必创建一个额外的递归方法或删除额外文件夹内的文件。这些都是通过调用自动完成的

DirectoryInfo.Delete ();

Details是在这里

像这样的东西效果很好:

  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作为变量传递给delete方法,将删除子文件和包含文件的子文件夹。