422 Stimmen

Verzeichnis kann nicht mit Directory.Delete(path, true) gelöscht werden

Ich verwende .NET 3.5 und versuche, ein Verzeichnis mit rekursiv zu löschen:

Directory.Delete(myPath, true);

Meines Erachtens sollte dies zu einem Fehler führen, wenn Dateien in Gebrauch sind oder ein Problem mit den Zugriffsrechten besteht, aber ansonsten sollten das Verzeichnis und sein gesamter Inhalt gelöscht werden.

Gelegentlich erhalte ich jedoch diese Meldung:

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)
    ...

Ich bin nicht überrascht, dass die Methode manchmal abbricht, aber ich bin überrascht, dass ich diese spezielle Meldung erhalte, wenn rekursiv wahr ist (ich wissen das Verzeichnis ist nicht leer.)

Gibt es einen Grund, warum ich dies anstelle von AccessViolationException sehen würde?

15voto

Drejc Punkte 13878

Ich hatte genau das gleiche Problem unter Delphi. Und das Endergebnis war, dass meine eigene Anwendung das Verzeichnis, das ich löschen wollte, sperrte. Irgendwie wurde das Verzeichnis gesperrt, als ich in es schrieb (einige temporäre Dateien).

Der Haken an der Sache war, dass ich eine einfache Verzeichnis wechseln vor dem Löschen auf das übergeordnete Element übertragen.

13voto

Olivier de Rivoyre Punkte 1500

Sie können den Fehler reproduzieren, indem Sie ihn ausführen:

Directory.CreateDirectory(@"C:\Temp\a\b\c\");
Process.Start(@"C:\Temp\a\b\c\");
Thread.Sleep(1000);
Directory.Delete(@"C:\Temp\a\b\c");
Directory.Delete(@"C:\Temp\a\b");
Directory.Delete(@"C:\Temp\a");

Beim Versuch, das Verzeichnis 'b' zu löschen, wird die IOException "Das Verzeichnis ist nicht leer" ausgelöst. Das ist dumm, da wir gerade das Verzeichnis 'c' gelöscht haben.

Meines Erachtens liegt die Erklärung darin, dass das Verzeichnis "c" als gelöscht gekennzeichnet ist. Aber die Löschung ist noch nicht im System vermerkt. Das System hat geantwortet, dass die Aufgabe erledigt ist, obwohl sie in Wirklichkeit noch in Bearbeitung ist. Das System wartet wahrscheinlich darauf, dass der Datei-Explorer den Fokus auf das übergeordnete Verzeichnis legt, um die Löschung zu bestätigen.

Wenn Sie sich den Quellcode der Funktion Delete ansehen ( http://referencesource.microsoft.com/#mscorlib/system/io/directory.cs ) sehen Sie, dass er die native Funktion Win32Native.RemoveDirectory verwendet. Dieses "Do-not-wait"-Verhalten ist hier vermerkt:

Die Funktion RemoveDirectory markiert ein Verzeichnis zum Löschen beim Schließen. Daher wird das Verzeichnis erst entfernt, wenn der letzte Handle zum Verzeichnis geschlossen wird.

( http://msdn.microsoft.com/en-us/library/Windows/desktop/aa365488(v=vs.85).aspx )

Schlafen und neu versuchen ist die Lösung. Vgl. die Lösung von ryascl.

10voto

Piyush Soni Punkte 1298

Ich bin überrascht, dass niemand an diese einfache, nicht rekursive Methode gedacht hat, mit der Verzeichnisse, die schreibgeschützte Dateien enthalten, gelöscht werden können, ohne dass das Schreibschutz-Attribut jeder dieser Dateien geändert werden muss.

Process.Start("cmd.exe", "/c " + @"rmdir /s/q C:\Test\TestDirectoryContainingReadOnlyFiles"); 

(Ändern Sie etwas, um nicht sofort ein cmd-Fenster zu öffnen, das überall im Internet verfügbar ist)

8voto

Ich hatte diese seltsamen Rechteprobleme beim Löschen von Benutzerprofilverzeichnissen (in C:\Documents und Einstellungen), obwohl Sie dies in der Explorer-Shell tun können.

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

Es ist mir schleierhaft, was eine "Datei"-Operation mit einem Verzeichnis zu tun hat, aber ich weiß, dass es funktioniert, und das reicht mir!

3voto

citykid Punkte 8762

Das rekursive Löschen von Verzeichnissen, bei dem keine Dateien gelöscht werden, ist sicherlich unerwartet. Meine Lösung für dieses Problem:

public class IOUtils
{
    public static void DeleteDirectory(string directory)
    {
        Directory.GetFiles(directory, "*", SearchOption.AllDirectories).ForEach(File.Delete);
        Directory.Delete(directory, true);
    }
}

Ich habe Fälle erlebt, in denen dies geholfen hat, aber im Allgemeinen löscht Directory.Delete Dateien innerhalb von Verzeichnissen bei rekursiver Löschung, da dokumentiert in msdn .

Von Zeit zu Zeit begegnet mir dieses unregelmäßige Verhalten auch als Benutzer des Windows Explorer: Manchmal kann ich einen Ordner nicht löschen (es erscheint die unsinnige Meldung "Zugriff verweigert"), aber wenn ich nach unten gehe und die unteren Elemente lösche, kann ich auch die oberen Elemente löschen. Ich vermute also, dass der obige Code mit einer Anomalie des Betriebssystems zu tun hat - und nicht mit einem Problem der Basisklassenbibliothek.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X