Wenn Sie versuchen, das Verzeichnis rekursiv zu löschen, a
und das Verzeichnis a\b
im Explorer geöffnet ist, b
wird es gelöscht, aber Sie erhalten die Fehlermeldung "Verzeichnis ist nicht leer" a
, obwohl es leer ist, wenn Sie nachsehen. Das aktuelle Verzeichnis einer Anwendung (einschließlich Explorer) behält ein Handle für das Verzeichnis bei . Wenn Sie anrufen Directory.Delete(true)
, löscht sie von unten nach oben: b
, dann a
. Wenn b
es im Explorer geöffnet ist, erkennt der Explorer das Löschen von b
, wechselt das Verzeichnis nach oben cd ..
und bereinigt offene Handles. Da das Dateisystem asynchron arbeitet, Directory.Delete
schlägt der Vorgang aufgrund von Konflikten mit dem Explorer fehl.
Unvollständige Lösung
Ich habe ursprünglich die folgende Lösung veröffentlicht, mit der Idee, den aktuellen Thread zu unterbrechen, damit der Explorer Zeit hat, das Verzeichnishandle freizugeben.
// incomplete!
try
{
Directory.Delete(path, true);
}
catch (IOException)
{
Thread.Sleep(0);
Directory.Delete(path, true);
}
Dies funktioniert jedoch nur, wenn das geöffnete Verzeichnis das unmittelbare untergeordnete Verzeichnis des zu löschenden Verzeichnisses ist . Wenn a\b\c\d
im Explorer geöffnet ist und Sie diese a
Option verwenden, schlägt diese Technik nach dem Löschen von d
und fehl c
.
Eine etwas bessere Lösung
Diese Methode behandelt das Löschen einer tiefen Verzeichnisstruktur, selbst wenn eines der untergeordneten Verzeichnisse im Explorer geöffnet ist.
/// <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);
}
}
Trotz der zusätzlichen Arbeit, alleine zu rekursieren, müssen wir uns immer noch darum kümmernUnauthorizedAccessException
, was auf dem Weg passieren kann. Es ist nicht klar, ob der erste Löschversuch den Weg für den zweiten, erfolgreichen Versuch ebnet oder ob es nur die durch das Auslösen / Abfangen einer Ausnahme verursachte Zeitverzögerung ist, die es dem Dateisystem ermöglicht, aufzuholen.
Möglicherweise können Sie die Anzahl der Ausnahmen reduzieren, die unter typischen Bedingungen ausgelöst und abgefangen werden, indem Sie Thread.Sleep(0)
am Anfang des try
Blocks ein hinzufügen . Darüber hinaus besteht das Risiko, dass Sie unter starker Systemlast beide Directory.Delete
Versuche durchfliegen und fehlschlagen. Betrachten Sie diese Lösung als Ausgangspunkt für ein robusteres rekursives Löschen.
Allgemeine Antwort
Diese Lösung behandelt nur die Besonderheiten der Interaktion mit Windows Explorer. Wenn Sie einen soliden Löschvorgang wünschen, sollten Sie beachten, dass alles (Virenscanner, was auch immer) jederzeit einen offenen Griff zu dem haben kann, was Sie löschen möchten. Sie müssen es also später erneut versuchen. Wie viel später und wie oft Sie es versuchen, hängt davon ab, wie wichtig es ist, dass das Objekt gelöscht wird. Wie MSDN angibt ,
Robuster Dateiterationscode muss viele Komplexitäten des Dateisystems berücksichtigen.
Diese unschuldige Aussage, die nur einen Link zur NTFS-Referenzdokumentation enthält, sollte Ihre Haare aufstehen lassen.
( Bearbeiten : Viel. Diese Antwort hatte ursprünglich nur die erste, unvollständige Lösung.)