Wenn Sie versuchen, ein Verzeichnis rekursiv zu löschen a
und Verzeichnis a\b
im Explorer geöffnet ist, b
wird gelöscht, aber Sie erhalten die Fehlermeldung 'Verzeichnis ist nicht leer' für a
auch wenn sie leer ist, wenn man nachsieht. Das aktuelle Verzeichnis einer beliebigen Anwendung (einschließlich Explorer) behält einen Handle auf das Verzeichnis . Wenn Sie anrufen Directory.Delete(true)
löscht sie von unten nach oben: b
entonces a
. Wenn b
im Explorer geöffnet ist, erkennt der Explorer die Löschung von b
, Verzeichnis nach oben wechseln cd ..
und reinigen Sie offene Griffe. Da das Dateisystem asynchron arbeitet, ist die Directory.Delete
schlägt aufgrund von Konflikten mit dem Explorer fehl.
Unvollständige Lösung
Ursprünglich hatte ich die folgende Lösung gepostet, mit der Idee, den aktuellen Thread zu unterbrechen, damit Explorer Zeit hat, das Verzeichnis-Handle 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 sofort Unterverzeichnis des zu löschenden Verzeichnisses. Wenn a\b\c\d
im Explorer geöffnet ist und Sie diesen auf a
scheitert diese Technik nach dem Löschen von d
y c
.
Eine etwas bessere Lösung
Mit dieser Methode kann eine tiefe Verzeichnisstruktur auch dann gelöscht werden, 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 des zusätzlichen Aufwands, den die Wiederholungsprüfung für uns mit sich bringt, haben wir todavía müssen sich um die UnauthorizedAccessException
die auf dem Weg dorthin auftreten können. Es ist nicht klar, ob der erste Löschversuch den Weg für den zweiten, erfolgreichen Löschversuch ebnet, oder ob das Dateisystem durch die Verzögerung, die durch das Auslösen/Auffangen einer Ausnahme entsteht, die Möglichkeit hat, den Rückstand aufzuholen.
Sie können die Anzahl der ausgelösten und abgefangenen Ausnahmen unter typischen Bedingungen verringern, indem Sie eine Thread.Sleep(0)
zu Beginn der try
Block. Darüber hinaus besteht die Gefahr, dass Sie bei starker Systembelastung durch beide Blöcke fliegen. Directory.Delete
versuchen und scheitern. Betrachten Sie diese Lösung als Ausgangspunkt für eine robustere rekursive Löschung.
Allgemeine Antwort
Diese Lösung befasst sich nur mit den Besonderheiten der Interaktion mit dem Windows Explorer. Wenn Sie einen felsenfesten Löschvorgang wünschen, sollten Sie bedenken, dass alles (Virenscanner, was auch immer) jederzeit einen offenen Zugriff auf das, was Sie zu löschen versuchen, haben könnte. Sie müssen es also später noch einmal 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 zeigt an ,
Ein robuster Datei-Iterationscode muss viele Komplexitäten berücksichtigen des Dateisystems berücksichtigen.
Diese unschuldige Aussage, die nur mit einem Link zur NTFS-Referenzdokumentation versehen ist, sollte Ihnen die Haare zu Berge stehen lassen.
( 編集 : Sehr viel. Diese Antwort enthielt ursprünglich nur die erste, unvollständige Lösung).