Не удалить каталог с Каталогом. Удалите (путь, верный)

370
задан FunctionR 9 August 2014 в 23:15
поделиться

9 ответов

Примечание редактора: , Хотя этот ответ содержит немного полезной информации, это фактически неправильно о работах Directory.Delete. Прочитайте комментарии для этого ответа и других ответов на этот вопрос.

<час>

я столкнулся с этой проблемой прежде.

корень проблемы - то, что эта функция не удаляет файлы, которые являются в структуре каталогов. Таким образом, то, что необходимо будет сделать, создают функцию, которая удаляет все файлы в структуре каталогов тогда все каталоги прежде, чем удалить сам каталог. Я знаю, что это идет вразрез со вторым параметром, но это - намного более безопасный подход. Кроме того, Вы, вероятно, захотите удалить атрибуты ДОСТУПА ТОЛЬКО ДЛЯ ЧТЕНИЯ из файлов прямо перед удалением их. Иначе это повысит исключение.

Просто удар этот код в Ваш проект.

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

кроме того, для меня я лично добавляю ограничение на области машины, которым позволяют быть удаленными, потому что делают Вы хотите, чтобы кто-то вызвал эту функцию на C:\WINDOWS (%WinDir%) или C:\.

223
ответ дан user247702 23 November 2019 в 00:05
поделиться

Он возможный, что у Вас есть состояние состязания, где другой поток или процесс добавляют файлы к каталогу:

последовательность была бы:

процесс Средства удаления A:

  1. Пустеют, каталог
  2. Удаляют (теперь пустой) каталог.

, Если кто-то еще добавляет файл между 1 & 2, тогда возможно, 2 выдал бы перечисленное исключение?

2
ответ дан Douglas Leeder 23 November 2019 в 00:05
поделиться

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

0
ответ дан configurator 23 November 2019 в 00:05
поделиться

У меня была та же самая проблема под Дельфи. И конечный результат состоял в том, что мое собственное приложение блокировало каталог, который я хотел удалить. Так или иначе каталог был заблокирован, когда я писал в него (некоторые временные файлы).

выгода 22 была, я сделал простое каталог изменения к, он - родитель прежде, чем удалить его.

14
ответ дан Drejc 23 November 2019 в 00:05
поделиться

Каталог или файл в нем заблокированы и не могут быть удалены. Найдите преступника, который блокирует его, и посмотрите, можно ли устранить его.

1
ответ дан Vilx- 23 November 2019 в 00:05
поделиться

Вы не должны создать и дополнительный метод для recursivity или удалить файлы в дополнительной папке. Это все выполнение автоматически путем вызова

DirectoryInfo. Удалите ();

Детали здесь .

Что-то вроде этого работает довольно хорошее:

  var directoryInfo = new DirectoryInfo("My directory path");
    // Delete all files from app data directory.

    foreach (var subDirectory in directoryInfo.GetDirectories())
    {
          subDirectory.Delete(true);// true set recursive paramter, when it is true delete sub file and sub folder with files too
    }

передача, верная, поскольку, переменная для удаления метода, удалит sub файлы и sub папку с файлами также.

0
ответ дан 23 November 2019 в 00:05
поделиться

У меня возникли странные проблемы с разрешениями при удалении каталогов профиля пользователя (в C: \ Documents and Settings), несмотря на то, что я мог сделать это в оболочке Explorer.

File.SetAttributes(target_dir, FileAttributes.Normal);
Directory.Delete(target_dir, false);

Для меня это не имеет смысла. что делает "файловая" операция с каталогом, но я знаю, что она работает, и мне этого достаточно!

7
ответ дан 23 November 2019 в 00:05
поделиться

Если вы пытаетесь рекурсивно удалить каталог a и каталог a \ b открыт в проводнике, b будет удален, но вы получите ошибку «каталог не пуст» для a , даже если он пуст, когда вы пойдете и посмотрите. Текущий каталог любого приложения (включая Explorer) сохраняет дескриптор каталога . Когда вы вызываете Directory.Delete (true) , он удаляет снизу вверх: b , затем a . Если b открыт в проводнике, Explorer обнаружит удаление b , сменит каталог вверх cd .. и очистите открытые ручки. Поскольку файловая система работает асинхронно, каталог Directory. Операция удаления завершилась неудачно из-за конфликтов с проводником.

Неполное решение

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

// incomplete!
try
{
    Directory.Delete(path, true);
}
catch (IOException)
{
    Thread.Sleep(0);
    Directory.Delete(path, true);
}

Но это работает только в том случае, если открытый каталог является непосредственным потомком удаляемого каталога. Если a \ b \ c \ d открыт в проводнике, и вы используете его на a , этот метод не сработает после удаления d и c .

Несколько лучшее решение

Этот метод будет обрабатывать удаление глубокой структуры каталогов, даже если один из каталогов нижнего уровня открыт в проводнике.

/// <summary>
/// Depth-first recursive delete, with handling for descendant 
/// directories open in Windows Explorer.
/// </summary>
public static void DeleteDirectory(string path)
{
    foreach (string directory in Directory.GetDirectories(path))
    {
        DeleteDirectory(directory);
    }

    try
    {
        Directory.Delete(path, true);
    }
    catch (IOException) 
    {
        Directory.Delete(path, true);
    }
    catch (UnauthorizedAccessException)
    {
        Directory.Delete(path, true);
    }
}

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

Возможно, вы сможете для уменьшения количества генерируемых и перехватываемых исключений в типичных условиях путем добавления Thread.Sleep (0) в начало блока try . Кроме того, существует риск того, что при большой загрузке системы вы можете выполнить обе попытки Directory.Delete и потерпят неудачу. Считайте это решение отправной точкой для более надежного рекурсивного удаления.

Общий ответ

Это решение затрагивает только особенности взаимодействия с проводником Windows. Если вам нужна надежная операция удаления, нужно иметь в виду, что что угодно (сканер вирусов, что угодно) может иметь открытый дескриптор того, что вы пытаетесь удалить, в любое время. Так что вам придется повторить попытку позже. Через какое время и сколько раз вы будете пытаться, это зависит от того, насколько важно удалить объект. Как MSDN указывает ,

Надежный код итерации файла должен учитывать многие сложности. зависит от того, насколько важно удалить объект. Как MSDN указывает ,

Надежный код итерации файла должен учитывать многие сложности. зависит от того, насколько важно удалить объект. Как MSDN указывает ,

Надежный код итерации файла должен учитывать многие сложности. файловой системы.

Это невинное заявление, снабженное только ссылкой на справочную документацию NTFS, должно заставить вас всколыхнуть волосы.

( Edit : Много. Этот ответ только первоначально имел первое неполное решение.)

175
ответ дан 23 November 2019 в 00:05
поделиться

Похоже, что наличия пути или подпапки, выбранной в проводнике Windows, достаточно, чтобы заблокировать однократное выполнение Directory.Delete (path, true), вызывая исключение IOException как описано выше, и умирает вместо того, чтобы загрузить проводник Windows в родительскую папку и продолжить работу, как ожидалось.

1
ответ дан 23 November 2019 в 00:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: