42

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.

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. 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..

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.

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
Community
  • 1
  • 1
Subliminal Hash
  • 13,614
  • 20
  • 73
  • 104
  • what are your folder permissions? – northpole Sep 13 '12 at 21:37
  • I have full control.. as a side note, the folders are created programatically too.. – Subliminal Hash Sep 13 '12 at 21:39
  • I guess you got the above from http://stackoverflow.com/questions/329355/cannot-delete-directory-with-directory-deletepath-true - are you sure the folder isn't open in Windows Explorer, for example as per the other answers? Could something else still have a lock on the folder? – dash Sep 13 '12 at 21:41
  • I would suggest to `Sleep(..)` the executing thread for a second. Probbably windows yet removing files from it, in the moment your call your last instruction... – Tigran Sep 13 '12 at 21:43
  • 15
    @Tigran Peppering code with Sleep to make it work is the equivalent of smacking your TV on the side to make it work again. – MrDosu Nov 08 '13 at 15:25
  • possible duplicate of [delete a directory having subdirectory (not empty)](http://stackoverflow.com/questions/5933764/delete-a-directory-having-subdirectory-not-empty) – nawfal Feb 10 '14 at 07:50

6 Answers6

47

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

petro.sidlovskyy
  • 5,075
  • 1
  • 25
  • 29
  • What exception did you get when using it? It's .NET framework method and it should work unless you have some issues with permissions. – petro.sidlovskyy Sep 13 '12 at 21:41
  • 15
    Also from documentation: 'In some cases, if you have the specified directory open in File Explorer, the Delete method may not be able to delete it.' – petro.sidlovskyy Sep 13 '12 at 21:43
  • I am updating my question to include the exception message.. The directory is not open in file explorer.. – Subliminal Hash Sep 13 '12 at 21:44
  • Sorry could you please let us know what error have you got when tried Directory.Delete(target_dir, true); ? Was it the same 'The directory is not empty'? – petro.sidlovskyy Sep 13 '12 at 21:48
  • 6
    Ok, I tried it again with only Directory.Delete(target_dir, true) and I confirm the error message is exactly the same.. Also, tried thread.sleep for two seconds, and still the same error.. this is driving me mad! – Subliminal Hash Sep 13 '12 at 21:52
  • OK in this case please take a look here http://msdn.microsoft.com/en-us/library/fxeahc5f.aspx in the table with exceptions find IOException there are mentions all reasons why you may get this exceptions (e.g 'A file with the same name and location specified by path exists.'). Please make sure your directory doesn't satisfy any of these conditions. – petro.sidlovskyy Sep 13 '12 at 21:55
  • thank you guys for all the help.. I still have problems solving this issue. When and if I do, I'll post it here to share.. – Subliminal Hash Sep 13 '12 at 22:19
  • 1
    any hope on this problem? I'm still struggling with it – sees Mar 14 '13 at 10:40
  • @sees nope, I still have it. If and when you do, I would be glad to hear the solution.. – Subliminal Hash May 22 '13 at 17:24
  • 1
    The question explicitly says, that this does not work. (And it is known to not work, if the directory contains for example read only files. The fact that an exception is thrown is nice, but does not help in actually deleting the folder.) If people would use this function, it seems to me that the software will mostly work, but sometimes not. – Micha Wiedenmann Aug 31 '15 at 09:31
  • @petro I got this `Exception` because of directory is open in **File Explorer**,I think it is better to say that in your answer not in comments – mohsen Jun 04 '16 at 17:35
  • `Directory.Delete(target_dir, true);` works perfectly for me. – Junius Jan 12 '18 at 03:19
17

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);
}
Mika
  • 171
  • 1
  • 2
16

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.

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.

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.

enter image description here

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). THIS IS WHAT CAUSES THE ISSUE, at least for me. If in this situation we call Directory.Delete(dirPath, recursive: true); for the dirPath of 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 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.

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.

RonC
  • 31,330
  • 19
  • 94
  • 139
  • What if the error is retrown again inside the catch block? Should we run the code you show as many times as necessary until the error stops happening? Or does it always work on the second try inside the catch block? Or, yet, should we just try a couple of times before giving up on deleting the folder? – Ulysses Alves Sep 27 '19 at 12:29
  • 1
    If it throws in the catch block here then there is probably a legitimate reason why the directory can't be deleted (e.g. contains file that is open, contains file that you don't have permission to delete, etc) – RonC Sep 27 '19 at 12:35
  • This worked for me. But I didn't need to wait 2000 milliseconds, only 1: Thread.Sleep(1) – John Pankowicz Apr 07 '20 at 21:45
11

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

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.

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.

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

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.

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.

Source
Source

Tim Post
  • 33,371
  • 15
  • 110
  • 174
Dave
  • 8,163
  • 11
  • 67
  • 103
  • Wow! Thanks for all this info. The only thing I've never tried to solve this (yes, it remains unsolved!) is to use .Close I'll give it a try and let you know. I really do appreciate your post and intentions regarding helping others. Thanks.. – Subliminal Hash Feb 19 '13 at 09:15
  • http://stackoverflow.com/a/12544296/206730 "It is probably because of some kind of delays/caching in Windows Explorer." – Kiquenet Jul 19 '13 at 07:56
  • 1
    @Kiquenet In the end, I went through each file and folder, and changed it from read only. I then waited N amount of time (incase of AV scans). I then tried to delete, on fail, I renamed the file/folder and then tried again. This was 100% succesful although seems some what over the top to just delete and hardly ever needed to use the renaming, but the MSDN does explain it's an option (although I can't find the page now)! – Dave Jul 19 '13 at 09:34
  • None and I no longer have access - I'm really sorry... but it is easy. Literally, get all the files as a string array, then iterate via each moving changing the attribute. Then, wait N seconds and try to delete. On exception, wait, rename the existing folders (in my case, the fault was the folder was read only)... – Dave Jul 19 '13 at 14:42
0

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.

Ramesh Durai
  • 2,666
  • 9
  • 32
  • 55
0

To delete the given directory and if indicated, any subdirectories and files in the directory.

Directory.Delete(FolderPath, true); 
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77