为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

DIEA 2019-07-25 19:47:24
无法使用Directory.Delete删除目录(路径,true)我正在使用.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?
查看完整描述

3 回答

?
一只甜甜圈

TA贡献1836条经验 获得超5个赞

尽管这个答案包含一些有用的信息,但事实上它的工作原理是不正确的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:\


查看完整回答
反对 回复 2019-07-25
?
慕哥6287543

TA贡献1831条经验 获得超10个赞

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

不完整的解决方案

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

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

但这仅在打开目录是要删除的目录的直接子目录时才有效。如果a\b\c\d在资源管理器中打开并且您使用此功能a,则删除d和后此技术将失败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块的开头添加a来减少在典型条件下抛出和捕获的异常数。此外,存在一种风险,即在系统负载较重的情况下,您可以通过两次Directory.Delete尝试并且失败。将此解决方案视为更强大的递归删除的起点。

一般答案

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

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

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


查看完整回答
反对 回复 2019-07-25
  • 3 回答
  • 0 关注
  • 3152 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信