Невозможно удалить каталог с помощью Directory.Delete (путь, истина) - PullRequest
359 голосов
/ 30 ноября 2008

Я использую .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?

Ответы [ 29 ]

1 голос
/ 21 июля 2015

Как упомянуто выше, «принятое» решение не срабатывает в точках повторной обработки - но люди все еще отмечают его (???). Существует гораздо более короткое решение, которое правильно копирует функциональность:

public static void rmdir(string target, bool recursive)
{
    string tfilename = Path.GetDirectoryName(target) +
        (target.Contains(Path.DirectorySeparatorChar.ToString()) ? Path.DirectorySeparatorChar.ToString() : string.Empty) +
        Path.GetRandomFileName();
    Directory.Move(target, tfilename);
    Directory.Delete(tfilename, recursive);
}

Я знаю, что не обрабатывает случаи разрешений, упомянутые позже, но для всех намерений и целей FAR BETTER обеспечивает ожидаемую функциональность оригинального / стокового Directory.Delete () намного меньше кода тоже .

Вы можете безопасно продолжить обработку, потому что старый каталог будет отсутствовать ... даже если он не исчезнет, ​​потому что «файловая система все еще догоняет» (или любое другое оправдание, которое MS дал для предоставления сломанной функции ) .

В качестве преимущества, если вы знаете, что целевой каталог большой / глубокий и не хотите ждать (или беспокоиться об исключениях), последнюю строку можно заменить на:

    ThreadPool.QueueUserWorkItem((o) => { Directory.Delete(tfilename, recursive); });

Вы все еще можете продолжать работу.

0 голосов
/ 01 декабря 2008

Если текущий каталог вашего приложения (или любого другого приложения) является тем, который вы пытаетесь удалить, это не будет ошибкой нарушения прав доступа, но каталог не будет пустым. Убедитесь, что это не ваше собственное приложение, изменив текущий каталог; также убедитесь, что каталог не открыт в какой-либо другой программе (например, Word, Excel, Total Commander и т. д.). Большинство программ перейдут в каталог последнего открытого файла, что может привести к этому.

0 голосов
/ 28 октября 2016

Я решил один возможный случай указанной проблемы, когда методы были асинхронными и закодированы следующим образом:

// delete any existing update content folder for this update
if (await fileHelper.DirectoryExistsAsync(currentUpdateFolderPath))
       await fileHelper.DeleteDirectoryAsync(currentUpdateFolderPath);

С этим:

bool exists = false;                
if (await fileHelper.DirectoryExistsAsync(currentUpdateFolderPath))
    exists = true;

// delete any existing update content folder for this update
if (exists)
    await fileHelper.DeleteDirectoryAsync(currentUpdateFolderPath);

Вывод? Существует некоторый асинхронный аспект избавления от дескриптора, используемого для проверки существования, с которым Microsoft не смогла поговорить. Это как если бы асинхронный метод внутри оператора if содержал оператор if, действующий как оператор using.

0 голосов
/ 30 сентября 2016

добавить true во втором параметре.

Directory.Delete(path, true);

удалит все.

0 голосов
/ 03 марта 2015

Эта ошибка возникает, если какой-либо файл или каталог считается используемым. Это вводящая в заблуждение ошибка. Проверьте, открыты ли у вас какие-либо окна обозревателя или окна командной строки для какого-либо каталога в дереве или для программы, использующей файл в этом дереве.

0 голосов
/ 03 марта 2011

в случае сетевых файлов, Directory.DeleteHelper (recursive: = true) может вызвать IOException, что вызвано задержкой удаления файла

0 голосов
/ 06 декабря 2013

Ни один из приведенных выше ответов не работал для меня. Похоже, что использование моим собственным приложением DirectoryInfo в целевом каталоге приводило к тому, что оно оставалось заблокированным.

Похоже, что принудительное удаление мусора решило проблему, но не сразу. Несколько попыток удалить, где требуется.

Обратите внимание на Directory.Exists, так как он может исчезнуть после исключения. Я не знаю, почему удаление для меня было отложено (Windows 7 SP1)

        for (int attempts = 0; attempts < 10; attempts++)
        {
            try
            {
                if (Directory.Exists(folder))
                {
                    Directory.Delete(folder, true);
                }
                return;
            }
            catch (IOException e)
            {
                GC.Collect();
                Thread.Sleep(1000);
            }
        }

        throw new Exception("Failed to remove folder.");
0 голосов
/ 29 октября 2018

Я решил с помощью этой тысячелетней техники (вы можете оставить Thread. Спать в улове самостоятельно)

bool deleted = false;
        do
        {
            try
            {
                Directory.Delete(rutaFinal, true);                    
                deleted = true;
            }
            catch (Exception e)
            {
                string mensaje = e.Message;
                if( mensaje == "The directory is not empty.")
                Thread.Sleep(50);
            }
        } while (deleted == false);
0 голосов
/ 09 мая 2012

Я думаю, что есть файл, открытый некоторым потоком, о котором вы не знаете, у меня была та же проблема, и я решил ее, закрыв все потоки, которые указывали на каталог, который я хотел удалить.

...