Ошибка "Directory is not empty" при попытке программного удаления папки

В моем приложении я создал систему, в которой пользователи могут создавать галереи изображений. Фотографии хранятся в папках в формате category_name/gallery_name/{images} на диске. Каждая загруженная фотография сохраняется в соответствующей структуре каталогов, как указано выше.

При попытке удалить категорию, а также удалив из базы данных, я хочу также удалить соответствующие папки из системы. Когда я впервые получил сообщение об ошибке "Каталог не пуст", я искал и нашел это решение:

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

С помощью этого решения фотографии в папке "gallery_name" будут удалены просто отлично, тогда сама папка gallery_name будет удалена. Поэтому мы теперь остаемся с пустой папкой category_name. Затем последний бит кода в приведенной выше подпрограмме (Directory.Delete(target_dir, false);) вызывается для удаления папки category_name. Ошибка снова возникает.

Кто-нибудь знает об этом?

  • Directory.Delete(target_dir, true); не работал, поэтому я попробовал альтернативу.
  • У меня есть полный контроль над родительской папкой, и папки категории_имя и gallery_name также создаются программно без каких-либо проблем.
  • Как я уже упоминал, подкаталоги (папки галереи) и их содержимое (фотографии) удаляются с помощью этого кода. Это папка category_name, которая вызывает ошибку, хотя после этого кода это просто пустая папка.

Сообщение об ошибке, которое я получаю:

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

Ответ 1

Вы можете просто использовать Directory.Delete(target_dir, true); для рекурсивного удаления каталога и всех файлов. Вам не нужно писать пользовательскую функцию.

Ответ 2

Это работает для меня, хотя у меня есть 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);
}

Ответ 3

Это не так полно, как хотелось бы, но это то, что помогло мне в прошлом, когда я столкнулся с подобными проблемами.

Файл используется другим. Это означает, что вы создали папку/файл и еще не выпустили его. Используйте .Close() (если применимо).

Проблема, связанная с блокировкой.

Вы использовали Directory.Delete(rootFolder, true) (где true означает, что он рекурсивно решает), если в указанной корневой папке нет папок.

Открыт другой программой. Теперь у меня нет идеи, с чего начать, кроме установки Process Monitor, который может помочь, но это действительно работает только в некоторых ситуациях.

Такие вещи, как Anti Virus или даже (в Windows), такие вещи, как Defender, вызвали эту проблему в прошлом.

Когда вы вызываете Directory.Delete и файл открыт таким образом, Directory.Delete удаляет все файлы, но когда Directory.Delete вызывает RemoveDirectory, "каталог не пуст" исключение выбрано потому, что есть файл, помеченный для удаления, но фактически не удалены.

Очевидные вещи включают в себя убедитесь, что у вас есть разрешение на удаление папки (а не только на вас, но на учетную запись, в которой работает программа).

Файл, который вы пытаетесь удалить, только для чтения. Сначала измените атрибуты файлов всех файлов в папке только для чтения.

Путь разделяется другими компонентами Windows, поэтому вы можете создавать или удалять папки.

Источник
Источник

Ответ 4

Эта проблема сводила меня с ума. Я видел ТОЧНОЕ поведение плаката при использовании Directory.Delete(dirPath, recursive: true); для удаления каталога и его содержимого. И точно так же, как и плакат, несмотря на то, что вызов вызвал исключение, указав, что "Каталог не пуст". вызов фактически удалил все содержимое каталога рекурсивно, но не смог удалить корневой каталог предоставленного пути. Сумасшествие.

В моем случае я обнаружил, что проблема была вызвана , оставил ли дерево навигации в проводнике окон, открытый каталог, который я пытался удалить. Если это так, то, похоже, происходит какое-то случайное удаление или кеширование удаления содержимого каталога, что вызывает проблему. Такое поведение может казаться безвозвратным и непредсказуемым, потому что просмотр каталога в проводнике Windows, который должен быть удален, не вызывает этой проблемы , пока каталог не открыт в левом навигационном дереве Windows.

Возможно, необходимо сделать несколько снимков. Обратите внимание, что на пути ниже показано, что окно показывает 1346. 1346 является дочерним каталогом каталога 1001. В этом случае вызов для удаления 1346 рекурсивно будет успешным, потому что это не проблема, которую мы рассматриваем как 1346 в обозревателе Windows.

введите описание изображения здесь

Но на приведенном ниже рисунке обратите внимание, что на пути ниже мы смотрим каталог 1018. НО в левом небе мы открыли каталог 1349 (см. стрелку). ЭТО ЧТО ПРИНИМАЕТ ВОПРОС, по крайней мере для меня. Если в этой ситуации мы назовем Directory.Delete(dirPath, recursive: true); для dirPath каталога 1349, он выкинет "Каталог не пуст". исключение. Но если мы проверим каталог после возникновения исключения, мы обнаружим, что он удалил все содержимое каталога, и на самом деле он теперь пуст.

Таким образом, это похоже на сценарий краевого случая, но он может быть запущен, потому что, когда мы тестируем код, мы хотим посмотреть, удаляется ли папка. И это сложно понять, что вызывает его, потому что это о левой навигационной панели окна Explorer не основной области содержимого окна.

введите описание изображения здесь

В любом случае, насколько мне не нравится код ниже, он разрешает проблему для меня во всех случаях:

        //delete the directory and it 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 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);
            }
        }

Надеюсь, это поможет другим. Потребовалось довольно много времени, чтобы отследить и объяснить, потому что это действительно странное поведение.

Ответ 5

В моем случае я создал свой каталог с моей программой, запущенной как администратор. Когда я попытался удалить тот же каталог без прав администратора, я получил ошибку "Directory not empty".

Решение:. Запустите приложение как администратор или удалите его вручную.