简体   繁体   English

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

[英]“Directory is not empty” error when trying to programmatically delete a folder

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. 在磁盘上以category_name / gallery_name / {pictures}格式保存在文件夹中的照片。 Each uploaded photo is stored under relevant directory structure as given above. 每张上传的照片都存储在上面给出的相关目录结构下。

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 found this 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. 使用此解决方案,“gallery_name”文件夹中的照片被删除就好了,然后gallery_name文件夹本身被删除了。所以我们现在留下一个空的category_name文件夹。 Then the last bit of code in the above subroutine ( Directory.Delete(target_dir, false); ) gets called to delete the category_name folder. 然后调用上Directory.Delete(target_dir, false);例程( Directory.Delete(target_dir, false); )中的最后一部分代码来删除category_name文件夹。 The error raises again.. 错误再次引发..

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. 我可以完全控制父文件夹,也可以通过编程方式创建category_name和gallery_name文件夹,没有任何问题。
  3. As I mentioned, the sub directories (gallery_name folders) and their contents (photos) are deleted with this code just fine. 正如我所提到的,使用此代码删除子目录(gallery_name文件夹)及其内容(照片)就好了。 It is the category_name folder which causes the error, even though after this code, it is just an empty folder. 它是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

You may just use Directory.Delete(target_dir, true); 您可以只使用Directory.Delete(target_dir, true); to remove directory and all files recursively. 以递归方式删除目录和所有文件。 You don't have to write custom function. 您不必编写自定义功能。

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

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)您已使用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 Monitor which 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. 反病毒,甚至(在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 资源

This issue was driving me crazy. 这个问题让我抓狂。 I was seeing the EXACT behavior of the poster when using Directory.Delete(dirPath, recursive: true); 我在使用Directory.Delete(dirPath, recursive: true);时看到了海报的精确行为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. 疯狂。

In my case I found that the issue was brought on by whether left nav tree in 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左侧导航树中打开,查看要删除的Win​​dows资源管理器中的目录不会导致此问题。

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的问题。

在此输入图像描述

But in the picture below, notice that in the path below we are looking at directory 1018. BUT in the left nave we have directory 1349 opened up (see arrow). 但是在下面的图片中,请注意在下面的路径中我们正在查看目录1018. 但是在左中间我们打开了目录1349(参见箭头)。 THIS IS WHAT CAUSES THE ISSUE, at least for me. 这就是问题的原因,至少对我来说是这样。 If in this situation we call Directory.Delete(dirPath, recursive: true); 如果在这种情况下我们调用Directory.Delete(dirPath, recursive: true); for the dirPath of directory 1349 it will throw a "Directory is not empty." 对于目录1349的dirPath ,它将抛出“目录不为空”。 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 now empty. 但是如果我们在异常发生后检查目录,我们会发现它已经删除了目录的所有内容,实际上它现在是空的。

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资源管理器的左侧导航栏而不是窗口的主要内容区域。

在此输入图像描述

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. 追踪和解释花了相当多的时间,因为这真的很奇怪。

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. 解决方案:以管理员身份运行应用程序或手动删除它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM