C# 尝试以编程方式删除文件夹时出现“目录不为空”错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12415105/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 23:11:48  来源:igfitidea点击:

"Directory is not empty" error when trying to programmatically delete a folder

c#asp.net

提问by Subliminal Hash

In my app, I have built a system where users can create picture galleries. Photos held in folders in the format of category_name/gallery_name/{pictures} on disk. Each uploaded photo is stored under relevant directory structure as given above.

在我的应用程序中,我构建了一个系统,用户可以在其中创建图片库。磁盘上以 category_name/gallery_name/{pictures} 格式保存在文件夹中的照片。每张上传的照片都存储在上面给出的相关目录结构下。

When trying to delete a category though, as well as deleting from the database, I want to delete relevant folders from the system too. When I first received the error message "Directory is not empty" I searched and foundthis solution:

但是,在尝试删除类别以及从数据库中删除时,我也想从系统中删除相关文件夹。当我第一次收到错误消息“目录不为空”时,我搜索并找到了这个解决方案:

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

With this solution, photos in the "gallery_name" folder gets deleted just fine, then the gallery_name folder itself gets deleted fine.. so we are now left with an empty category_name folder. Then the last bit of code in the above subroutine (Directory.Delete(target_dir, false);) gets called to delete the category_name folder. The error raises again..

使用此解决方案,“gallery_name”文件夹中的照片被删除就好了,然后gallery_name 文件夹本身也被删除了……所以我们现在只剩下一个空的 category_name 文件夹。然后调用上述子程序 ( Directory.Delete(target_dir, false);) 中的最后一段代码以删除 category_name 文件夹。错误再次引发..

Does anyone knows a solution to this?

有谁知道这个问题的解决方案?

  1. Directory.Delete(target_dir, true);did not work, that is why I tried an alternative.
  2. I have full control over the parent folder and the category_name and gallery_name folders are also created programmatically without any problem.
  3. As I mentioned, the sub directories (gallery_name folders) and their contents (photos) are deleted with this code just fine. It is the category_name folder which causes the error, even though after this code, it is just an empty folder.
  1. Directory.Delete(target_dir, true);没有用,这就是我尝试替代方法的原因。
  2. 我可以完全控制父文件夹,并且 category_name 和 gallery_name 文件夹也是以编程方式创建的,没有任何问题。
  3. 正如我所提到的,使用此代码删除子目录(gallery_name 文件夹)及其内容(照片)就好了。这是导致错误的 category_name 文件夹,即使在此代码之后,它也只是一个空文件夹。

The exception message I get is:

我得到的异常消息是:

System.IO.IOException was unhandled by user code
  HResult=-2147024751
  Message=The directory is not empty.

  Source=mscorlib
  StackTrace:
       at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       at System.IO.Directory.DeleteHelper(String fullPath, String userPath, Boolean recursive, Boolean throwOnTopLevelDirectoryNotFound)
       at System.IO.Directory.Delete(String fullPath, String userPath, Boolean recursive, Boolean checkHost)
       at System.IO.Directory.Delete(String path)
       at MyApp.PhotoGallery.Categories.deleteCategory(Int32 cID, String categoryname) in d:\Documents\My Dropbox\web projects\MyAppFolder\App_Code\BLL\PhotoGallery.vb:line 291
       at _admhades_PhotoGallery.deleteCategory(Int32 categoryID, String categoryname) in d:\Documents\My Dropbox\web projects\HavadisPre\_admhades\PhotoGallery.aspx.vb:line 71

回答by petro.sidlovskyy

You may just use Directory.Delete(target_dir, true);to remove directory and all files recursively. You don't have to write custom function.

您可以只使用Directory.Delete(target_dir, true);递归删除目录和所有文件。您不必编写自定义函数。

回答by Dave

This isn't as complete as I'd like, but these are things that have helped me in the past when I faced similar issues.

这并不像我想要的那么完整,但这些是过去当我遇到类似问题时对我有所帮助的东西。

The file is in use by something else. This means you've created a folder/file and have not yet released it. Use .Close() (where applicable).

该文件正被其他东西使用。这意味着您已经创建了一个文件夹/文件,但尚未发布。使用 .Close() (如果适用)。

A lock related issue.

一个锁相关的问题。

You have used the Directory.Delete(rootFolder, true)(where true means delete recursively) when there are no folders within the root folder specified.

Directory.Delete(rootFolder, true)当指定的根文件夹中没有文件夹时,您已经使用了(其中 true 表示递归删除)。

It is open by another program. Now, I have NO idea where to begin on this other than installing Process Monitorwhich can help but that only really works in some situations.

它由另一个程序打开。现在,我不知道从哪里开始,除了安装Process Monitor可以提供帮助,但这仅在某些情况下才真正有效。

Things like Anti Virus, or even (on Windows) things like Defender have caused this issue in the past.

像 Anti Virus 之类的东西,甚至(在 Windows 上)Defender 之类的东西过去都曾导致过这个问题。

When you call Directory.Delete and a file is open in such way, Directory.Delete succeeds in deleting all files but when Directory.Delete calls RemoveDirectory a "directory is not empty" exception is thrown because there is a file marked for deletion but not actually deleted.

当您调用 Directory.Delete 并且文件以这种方式打开时,Directory.Delete 成功删除所有文件,但是当 Directory.Delete 调用 RemoveDirectory 时,会引发“目录不为空”异常,因为存在标记为删除但未标记为删除的文件实际上删除了。

The obvious things includes make sure you have permission to delete the folder (not just you, but the account the program runs under).

显而易见的事情包括确保您有权删除该文件夹(不仅是您,还有运行程序的帐户)。

The file you are trying to delete is readonly. Change the file attributes of all files in the folder first from read-only.

您尝试删除的文件是只读的。首先将文件夹中所有文件的文件属性从只读更改。

The path is shared by other Windows components so becareful where you are creating/deleting folders.

该路径由其他 Windows 组件共享,因此在创建/删除文件夹时要小心。

Source
Source

来源
来源

回答by Mika

This works for me, even though i have File Explorer open:

这对我有用,即使我打开了文件资源管理器:

public static void DeleteFilesAndFoldersRecursively(string target_dir)
{
    foreach (string file in Directory.GetFiles(target_dir))
    {
        File.Delete(file);
    }

    foreach (string subDir in Directory.GetDirectories(target_dir))
    {
        DeleteFilesAndFoldersRecursively(subDir);
    }

    Thread.Sleep(1); // This makes the difference between whether it works or not. Sleep(0) is not enough.
    Directory.Delete(target_dir);
}

回答by Ramesh Durai

In my case, I have created my directory with my program running as administrator. When I tried to delete the same directory without administrator rights, I got the "Directory is not empty" error.

就我而言,我已经创建了我的目录,我的程序以管理员身份运行。当我尝试在没有管理员权限的情况下删除同一目录时,出现“目录不为空”错误。

Solution:Either run the application as administrator or delete it manually.

解决方案:以管理员身份运行应用程序或手动删除它。

回答by Ron C

This issue was driving me crazy. I was seeing the EXACT behavior of the poster when using Directory.Delete(dirPath, recursive: true);to delete a directory and it's contents. And just like the poster, even though the call threw an exception stating "Directory is not empty." the call had actually deleted all the contents of the directory recursively BUT failed to delete the root directory of the path provided. Craziness.

这个问题快把我逼疯了。Directory.Delete(dirPath, recursive: true);用于删除目录及其内容时,我看到了海报的确切行为。就像海报一样,即使调用抛出了一个异常,指出“目录不为空”。该调用实际上已递归删除目录的所有内容,但未能删除所提供路径的根目录。疯狂。

In my case I found that the issue was brought on by whether left nav treein window's explorer showed the directory open which I was trying to delete. If so, then some sort of queued delete or caching of the delete of the directory's contents seems to be occurring causing the issue. This behavior can seem squirrely and unpredictable because viewing the directory in windows explorer that is to be deleted does not cause this issue as long as the directory is not open in the Windows left nav tree.

在我的情况下,我发现问题是由窗口资源管理器中的左侧导航树是否显示我试图删除的目录打开引起的。如果是这样,那么似乎正在发生某种排队删除或缓存删除目录内容的问题。这种行为看起来很奇怪且不可预测,因为只要在 Windows 左侧导航树中未打开该目录,在 Windows 资源管理器中查看要删除的目录就不会导致此问题。

A few pictures are probably necessary to make this clear. Notice in the path below that the window is showing 1346. 1346 is a child directory of directory 1001. In this case a call to delete 1346 recursively will succeed because it's not an issue that we are looking at 1346 in Window's explorer per se.

可能需要几张图片才能清楚地说明这一点。请注意,在下面的路径中,窗口显示的是 1346。1346 是目录 1001 的子目录。在这种情况下,递归删除 1346 的调用将成功,因为我们在 Window 的资源管理器中查看 1346 本身并不是问题。

enter image description here

在此处输入图片说明

But in the picture below, notice that in the path below we are looking at directory 1018. BUTin the left nave we have directory 1349 opened up (see arrow). THIS IS WHAT CAUSES THE ISSUE, at least for me. If in this situation we call Directory.Delete(dirPath, recursive: true);for the dirPathof directory 1349 it will throw a "Directory is not empty." exception. But if we check the directory after the exception occurrs we will find that it has deleted all the contents of the directory and it is in fact nowempty.

但是在下图中,请注意在下面的路径中,我们正在查看目录 1018。 但是在左侧中殿,我们打开了目录 1349(见箭头)。这就是导致问题的原因,至少对我而言。如果在这种情况下,我们呼吁Directory.Delete(dirPath, recursive: true);dirPath目录1349的它会抛出一个“目录不是空的。” 例外。但是如果我们在异常发生后查看目录,我们会发现它已经删除了目录中的所有内容,实际上现在是空的。

So this seems very much like an edge case scenario but it's one we developers can run into because when we are testing code we are wanting to watch to see if the folder gets deleted. And it's challenging to understand what's triggering it because it's about the left nav bar of windows explorer not the main contents area of the window.

所以这看起来很像一种边缘情况,但我们开发人员可能会遇到这种情况,因为当我们测试代码时,我们想查看文件夹是否被删除。而且很难理解是什么触发了它,因为它与 Windows 资源管理器的左侧导航栏有关,而不是窗口的主要内容区域。

enter image description here

在此处输入图片说明

Anyway, as much as I dislike the code below, it does solve the problem for me in all cases:

无论如何,尽管我不喜欢下面的代码,但它确实为我解决了所有情况下的问题:

        //delete the directory and it's contents if the directory exists
        if (Directory.Exists(dirPath)) {
            try {
                Directory.Delete(dirPath, recursive: true);                //throws if directory doesn't exist.
            } catch {
                //HACK because the recursive delete will throw with an "Directory is not empty." 
                //exception after it deletes all the contents of the diretory if the directory
                //is open in the left nav of Windows's explorer tree.  This appears to be a caching
                //or queuing latency issue.  Waiting 2 secs for the recursive delete of the directory's
                //contents to take effect solved the issue for me.  Hate it I do, but it was the only
                //way I found to work around the issue.
                Thread.Sleep(2000);     //wait 2 seconds
                Directory.Delete(dirPath, recursive: true);
            }
        }

I hope this helps others. It took quite a bit of time to track down and explain because it's really odd behavior.

我希望这对其他人有帮助。追查和解释花了很多时间,因为这真的很奇怪。