Ich verwende .NET 3.5 und versuche, ein Verzeichnis rekursiv zu löschen, indem ich:
Directory.Delete(myPath, true);
Meines Wissens nach sollte dies ausgelöst werden, wenn Dateien verwendet werden oder ein Berechtigungsproblem vorliegt. Andernfalls sollte das Verzeichnis und der gesamte Inhalt gelöscht werden.
Ich bekomme jedoch gelegentlich Folgendes:
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 auslöst, aber ich bin überrascht, diese bestimmte Nachricht zu erhalten, wenn rekursiv wahr ist. (Ich weiß, dass das Verzeichnis nicht leer ist.)
Gibt es einen Grund, warum ich dies anstelle von AccessViolationException sehen würde?
Antworten:
Anmerkung des Herausgebers: Obwohl diese Antwort einige nützliche Informationen enthält, ist sie in Bezug auf die Funktionsweise von sachlich falsch
Directory.Delete
. Bitte lesen Sie die Kommentare zu dieser Antwort und andere Antworten auf diese Frage.Ich bin schon einmal auf dieses Problem gestoßen.
Die Ursache des Problems liegt darin, dass diese Funktion keine Dateien löscht, die sich in der Verzeichnisstruktur befinden. Sie müssen also eine Funktion erstellen, die alle Dateien in der Verzeichnisstruktur und dann alle Verzeichnisse löscht, bevor Sie das Verzeichnis selbst entfernen. Ich weiß, dass dies gegen den zweiten Parameter verstößt, aber es ist ein viel sichererer Ansatz. Darüber hinaus möchten Sie wahrscheinlich READ-ONLY-Zugriffsattribute aus den Dateien entfernen, bevor Sie sie löschen. Andernfalls wird eine Ausnahme ausgelöst.
Fügen Sie diesen Code einfach in Ihr Projekt ein.
Außerdem füge ich persönlich eine Einschränkung für Bereiche des Computers hinzu, die gelöscht werden dürfen, weil Sie möchten, dass jemand diese Funktion auf
C:\WINDOWS (%WinDir%)
oder aufruftC:\
.quelle
Directory.Delete(path, true)
die keine Dateien löscht, ist falsch. Siehe MSDN msdn.microsoft.com/en-us/library/fxeahc5f.aspxDirectory.Delete(string,bool)
fehlschlägt, ist etwas gesperrt oder falsch zugelassen, und es gibt keine einheitliche Lösung für ein solches Problem. Die Leute müssen dieses Problem in ihrem Kontext ansprechen, und wir sollten nicht jede Idee mit dem Problem (mit Wiederholungsversuchen und Ausnahmeverschlucken) in den Griff bekommen und auf ein gutes Ergebnis hoffen.Wenn Sie versuchen, das Verzeichnis rekursiv zu löschen,
a
und das Verzeichnisa\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 anrufenDirectory.Delete(true)
, löscht sie von unten nach oben:b
, danna
. Wennb
es im Explorer geöffnet ist, erkennt der Explorer das Löschen vonb
, wechselt das Verzeichnis nach obencd ..
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.
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 diesea
Option verwenden, schlägt diese Technik nach dem Löschen vond
und fehlc
.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.
Trotz der zusätzlichen Arbeit, alleine zu rekursieren, müssen wir uns immer noch darum kümmern
UnauthorizedAccessException
, 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 destry
Blocks ein hinzufügen . Darüber hinaus besteht das Risiko, dass Sie unter starker Systemlast beideDirectory.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 ,
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.)
quelle
catch
Block ausgeführt (währenddessen gibt der Explorer das Verzeichnis immer noch frei, da kein Befehl gesendet wurde, um es anzuweisen, dies nicht zu tun). Der Aufruf vonThread.Sleep(0)
kann oder kann nicht notwendig sein, da dercatch
Block dem System bereits etwas mehr Zeit gegeben hat, aber ein wenig zusätzliche Sicherheit zu geringen Kosten bietet. Danach wird dasDelete
aufgerufen, wobei das Verzeichnis bereits freigegeben ist.Bevor Sie fortfahren, überprüfen Sie die folgenden Gründe, auf die Sie Einfluss haben:
Überprüfen Sie andernfalls die folgenden legitimen Gründe, die außerhalb Ihrer Kontrolle liegen:
Wenn eines der oben genannten Probleme auftritt, sollten Sie verstehen, warum dies geschieht, bevor Sie versuchen, Ihren Löschcode zu verbessern. Sollte Ihre App schreibgeschützte oder unzugängliche Dateien löschen? Wer hat sie so markiert und warum?
Wenn Sie die oben genannten Gründe ausgeschlossen haben, besteht immer noch die Möglichkeit von falschen Fehlern. Das Löschen schlägt fehl, wenn jemand ein Handle für eine der zu löschenden Dateien oder Ordner hat, und es gibt viele Gründe, warum jemand den Ordner auflistet oder seine Dateien liest:
Der allgemeine Ansatz zur Behandlung von Störfehlern besteht darin, es mehrmals zu versuchen und zwischen den Versuchen eine Pause einzulegen. Sie möchten es offensichtlich nicht für immer versuchen, also sollten Sie nach einer bestimmten Anzahl von Versuchen aufgeben und entweder eine Ausnahme auslösen oder den Fehler ignorieren. So was:
Meiner Meinung nach sollte ein solcher Helfer für alle Löschungen verwendet werden, da immer falsche Fehler möglich sind. Sie sollten diesen Code jedoch an Ihren Verwendungsfall anpassen und nicht nur blind kopieren.
Ich hatte falsche Fehler für einen internen Datenordner, der von meiner App unter% LocalAppData% generiert wurde. Meine Analyse sieht also folgendermaßen aus:
Der Ordner wird ausschließlich von meiner Anwendung gesteuert, und der Benutzer hat keinen gültigen Grund, Dinge in diesem Ordner als schreibgeschützt oder unzugänglich zu markieren. Daher versuche ich nicht, diesen Fall zu behandeln.
Es gibt dort keine wertvollen, vom Benutzer erstellten Inhalte, sodass kein Risiko besteht, versehentlich etwas mit Gewalt zu löschen.
Als interner Datenordner erwarte ich nicht, dass er im Explorer geöffnet ist, zumindest habe ich nicht das Bedürfnis, den Fall speziell zu behandeln (dh ich kann diesen Fall über den Support gut bearbeiten).
Wenn alle Versuche fehlschlagen, ignoriere ich den Fehler. Im schlimmsten Fall kann die App einige neuere Ressourcen nicht entpacken, stürzt ab und fordert den Benutzer auf, sich an den Support zu wenden. Dies ist für mich akzeptabel, solange dies nicht häufig vorkommt. Wenn die App nicht abstürzt, bleiben einige alte Daten zurück, was für mich wiederum akzeptabel ist.
Ich beschließe, Wiederholungsversuche auf 500 ms (50 * 10) zu beschränken. Dies ist eine willkürliche Schwelle, die in der Praxis funktioniert. Ich wollte, dass der Schwellenwert kurz genug ist, damit Benutzer die App nicht beenden, weil sie nicht mehr reagiert. Andererseits reicht eine halbe Sekunde für den Täter aus, um die Bearbeitung meines Ordners abzuschließen. Nach anderen SO-Antworten zu urteilen, die sich manchmal sogar
Sleep(0)
als akzeptabel herausstellen, werden nur sehr wenige Benutzer jemals mehr als einen einzigen Wiederholungsversuch erleben.Ich versuche es alle 50 ms erneut, was eine weitere willkürliche Zahl ist. Ich bin der Meinung, dass, wenn eine Datei beim Versuch, sie zu löschen, verarbeitet (indiziert, überprüft) wird, 50 ms ungefähr der richtige Zeitpunkt sind, um zu erwarten, dass die Verarbeitung in meinem Fall abgeschlossen ist. Außerdem sind 50 ms klein genug, um nicht zu einer merklichen Verlangsamung zu führen. Auch dies
Sleep(0)
scheint in vielen Fällen ausreichend zu sein, sodass wir nicht zu viel verzögern möchten.Der Code wiederholt alle E / A-Ausnahmen. Normalerweise erwarte ich keine Ausnahmen beim Zugriff auf% LocalAppData%. Daher habe ich mich für die Einfachheit entschieden und das Risiko einer Verzögerung von 500 ms für den Fall einer legitimen Ausnahme akzeptiert. Ich wollte auch keinen Weg finden, um die genaue Ausnahme zu erkennen, die ich erneut versuchen möchte.
quelle
Directory.Exists
möchten , berücksichtigen müssen, dass Sie sich in einem Rennen mit der Unklarheit befinden, ob das Verzeichnis seit dem letzten Versuch "gegangen" ist [und ein Niave- Wächter dies tun würde nicht lösen.]Moderne asynchrone Antwort
Die akzeptierte Antwort ist einfach falsch. Sie funktioniert möglicherweise für einige Benutzer, da die Zeit, die zum Abrufen von Dateien von der Festplatte benötigt wird, alles freisetzt, was die Dateien gesperrt hat. Tatsache ist, dass dies passiert, weil Dateien durch einen anderen Prozess / Stream / eine andere Aktion gesperrt werden. Die anderen Antworten verwenden
Thread.Sleep
(Yuck), um das Löschen des Verzeichnisses nach einiger Zeit erneut zu versuchen. Diese Frage muss mit einer moderneren Antwort überarbeitet werden.Unit Tests
Diese Tests zeigen ein Beispiel dafür, wie eine gesperrte Datei
Directory.Delete
zum Fehlschlagen führen kann und wie dieTryDeleteDirectory
oben beschriebene Methode das Problem behebt.quelle
Thread.Sleep
Sie sie heute vermeiden sollten, und verwenden stattdessenasync
/await
mitTask.Delay
. Das ist verständlich, das ist eine sehr alte Frage.BC36943 'Await' cannot be used inside a 'Catch' statement, a 'Finally' statement, or a 'SyncLock' statement.
if (!Directory.Exists(directoryPath)) { return true; } await Task.Delay(millisecondsDelay);
, um zu warten, bis das Verzeichnis wirklich verschwunden istEine wichtige Sache, die erwähnt werden sollte (ich hatte sie als Kommentar hinzugefügt, aber ich darf nicht), ist, dass sich das Verhalten der Überladung von .NET 3.5 auf .NET 4.0 geändert hat.
Ab .NET 4.0 werden Dateien im Ordner selbst gelöscht, jedoch NICHT in 3.5. Dies ist auch in der MSDN-Dokumentation zu sehen.
.NET 4.0
.NET 3.5
quelle
Ich hatte das gleiche Problem unter Delphi. Das Endergebnis war, dass meine eigene Anwendung das Verzeichnis sperrte, das ich löschen wollte. Irgendwie wurde das Verzeichnis gesperrt, als ich darauf schrieb (einige temporäre Dateien).
Der Haken 22 war, ich habe ein einfaches Änderungsverzeichnis gemacht vor dem Löschen für das übergeordnete habe.
quelle
Ich bin überrascht, dass niemand an diese einfache nicht rekursive Methode gedacht hat, mit der Verzeichnisse mit schreibgeschützten Dateien gelöscht werden können, ohne dass das schreibgeschützte Attribut der einzelnen Dateien geändert werden muss.
(Ändern Sie ein wenig, um ein cmd-Fenster, das im gesamten Internet verfügbar ist, nicht vorübergehend auszulösen.)
quelle
Sie können den Fehler reproduzieren, indem Sie Folgendes ausführen:
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.
Nach meinem Verständnis ist die Erklärung, dass das Verzeichnis 'c' als gelöscht gestempelt ist. Das Löschen ist jedoch noch nicht im System festgeschrieben. Das System hat eine Antwort, der Auftrag ist erledigt, während er tatsächlich noch verarbeitet wird. Das System wartet wahrscheinlich, bis sich der Datei-Explorer auf das übergeordnete Verzeichnis konzentriert hat, um das Löschen festzuschreiben.
Wenn Sie sich den Quellcode der Löschfunktion ( http://referencesource.microsoft.com/#mscorlib/system/io/directory.cs ) ansehen, werden Sie feststellen, dass die native Win32Native.RemoveDirectory-Funktion verwendet wird. Dieses Warteverhalten wird hier vermerkt:
( http://msdn.microsoft.com/en-us/library/windows/desktop/aa365488(v=vs.85).aspx )
Schlaf und Wiederholung ist die Lösung. Vgl. Die Lösung des Ryascl.
quelle
Ich hatte diese seltsamen Berechtigungsprobleme beim Löschen von Benutzerprofilverzeichnissen (in C: \ Dokumente und Einstellungen), obwohl dies in der Explorer-Shell möglich war.
Es macht für mich keinen Sinn, was eine "Datei" -Operation in einem Verzeichnis macht, aber ich weiß, dass es funktioniert und das reicht mir!
quelle
Diese Antwort basiert auf: https://stackoverflow.com/a/1703799/184528 . Der Unterschied zu meinem Code besteht darin, dass wir nur dann viele Unterverzeichnisse und Dateien löschen, wenn dies erforderlich ist. Ein Aufruf von Directory.Delete schlägt beim ersten Versuch fehl (was daran liegen kann, dass der Windows Explorer ein Verzeichnis betrachtet).
quelle
UnauthorizedAccessException
? Es würde einfach wieder werfen. Und wieder. Und wieder ... Weil es jedes Mal zu gehen gehtcatch
und die Funktion erneut aufruft. AThread.Sleep(0);
ändert Ihre Berechtigungen nicht. Es sollte nur den Fehler protokollieren und an diesem Punkt ordnungsgemäß fehlschlagen. Und diese Schleife wird nur so lange fortgesetzt, wie das (Unter-) Verzeichnis geöffnet ist - es wird nicht programmgesteuert geschlossen. Sind wir bereit, dies nur so lange zuzulassen, wie diese Dinge offen bleiben? Gibt es einen besseren Weg?UnauthorizedAccessException
, wird manuell versucht, jede Datei manuell zu löschen. Es macht also weiterhin Fortschritte, indem es in die Verzeichnisstruktur übergeht. Ja, möglicherweise löst jede Datei und jedes Verzeichnis dieselbe Ausnahme aus. Dies kann jedoch auch einfach auftreten, weil der Explorer ein Handle daran hält (siehe stackoverflow.com/a/1703799/184528 ). Ich werde "tryAgain" in "secondTry" ändern. um es klarer zu machen.Process.Kill()
jeden Prozess ausführen kann, durch den eine Datei gesperrt werden kann, und die Dateien löschen kann. Das Problem, auf das ich stoße, ist das Löschen eines Verzeichnisses, in dem eine dieser Dateien noch geöffnet war (siehe stackoverflow.com/questions/41841590/… ). Wenn Sie also diese Schleife durchlaufen, egal was sie sonst noch tut, schlägtDirectory.Delete()
sie immer noch fehl, wenn dieses Handle nicht freigegeben werden kann.UnauthorizedAccessException
Löschen von Dateien, da das Löschen von Dateien (vorausgesetzt, dies war sogar zulässig, da das Aufrufen dieses Codes fehlgeschlagen istDirectory.Delete()
) Ihnen nicht auf magische Weise die Berechtigung zum Löschen des Verzeichnisses erteilt.Keine der oben genannten Lösungen hat bei mir gut funktioniert. Am Ende habe ich eine bearbeitete Version der @ryascl-Lösung wie folgt verwendet:
quelle
Ist es möglich, dass Sie eine Race-Bedingung haben, bei der ein anderer Thread oder Prozess dem Verzeichnis Dateien hinzufügt:
Die Reihenfolge wäre:
Prozess A löschen:
Wenn jemand anderes eine Datei zwischen 1 und 2 hinzufügt, würde dann vielleicht 2 die aufgeführte Ausnahme auslösen?
quelle
Ich habe einige Stunden damit verbracht, dieses Problem und andere Ausnahmen mit dem Löschen des Verzeichnisses zu lösen. Das ist meine Lösung
Dieser Code hat die kleine Verzögerung, die für meine Anwendung nicht wichtig ist. Aber seien Sie vorsichtig, die Verzögerung kann ein Problem für Sie sein, wenn Sie viele Unterverzeichnisse in dem Verzeichnis haben, das Sie löschen möchten.
quelle
Das Löschen rekursiver Verzeichnisse, bei denen keine Dateien gelöscht werden, ist sicherlich unerwartet. Mein Fix dafür:
Ich habe Fälle erlebt, in denen dies geholfen hat, aber im Allgemeinen löscht Directory.Delete Dateien in Verzeichnissen beim rekursiven Löschen, wie in msdn dokumentiert .
Von Zeit zu Zeit stoße ich auch als Benutzer von Windows Explorer auf dieses unregelmäßige Verhalten: Manchmal kann ich einen Ordner nicht löschen (die unsinnige Meldung lautet "Zugriff verweigert"), aber wenn ich einen Drilldown durchführe und untere Elemente lösche, kann ich die oberen löschen Artikel auch. Ich denke, der obige Code befasst sich mit einer Betriebssystemanomalie - nicht mit einem Problem mit der Basisklassenbibliothek.
quelle
Das Verzeichnis oder eine Datei darin ist gesperrt und kann nicht gelöscht werden. Finden Sie den Täter, der es sperrt, und prüfen Sie, ob Sie es beseitigen können.
quelle
Es scheint, dass die Auswahl des Pfads oder Unterordners im Windows Explorer ausreicht, um eine einzelne Ausführung von Directory.Delete (Pfad, true) zu blockieren, eine IOException wie oben beschrieben auszulösen und zu sterben, anstatt Windows Explorer in einen übergeordneten Ordner zu booten und als zu verfahren erwartet.
quelle
Ich hatte heute dieses Problem. Es geschah, weil ich den Windows Explorer für das Verzeichnis geöffnet hatte, das gelöscht werden wollte, was dazu führte, dass der rekursive Aufruf fehlschlug und somit die IOException. Stellen Sie sicher, dass keine Handles für das Verzeichnis geöffnet sind.
Außerdem ist MSDN klar, dass Sie keine eigene Zusammenfassung schreiben müssen: http://msdn.microsoft.com/en-us/library/fxeahc5f.aspx
quelle
Ich hatte das gleiche Problem mit Windows Workflow Foundation auf einem Build-Server mit TFS2012. Intern wird der Workflow Directory.Delete () mit dem rekursiven Flag auf true gesetzt. In unserem Fall scheint es netzwerkbezogen zu sein.
Wir haben einen binären Ablageordner auf einer Netzwerkfreigabe gelöscht, bevor wir ihn neu erstellt und mit den neuesten Binärdateien gefüllt haben. Jeder andere Build würde fehlschlagen. Beim Öffnen des Ablageordners nach einem fehlgeschlagenen Build war der Ordner leer, was darauf hinweist, dass alle Aspekte des Aufrufs von Directory.Delete () erfolgreich waren, mit Ausnahme des Löschens des tatsächlichen Verzeichnisses.
Das Problem scheint auf die Asynchronität der Netzwerkdateikommunikation zurückzuführen zu sein. Der Build-Server wies den Dateiserver an, alle Dateien zu löschen, und der Dateiserver meldete dies, obwohl dies noch nicht vollständig geschehen war. Dann forderte der Build-Server das Löschen des Verzeichnisses an, und der Dateiserver lehnte die Anforderung ab, da das Löschen der Dateien noch nicht vollständig abgeschlossen war.
Zwei mögliche Lösungen in unserem Fall:
Die letztere Methode ist schnell und schmutzig, scheint aber den Trick zu tun.
quelle
Dies liegt an FileChangesNotifications.
Es passiert seit ASP.NET 2.0. Wenn Sie einen Ordner in einer App löschen, wird dieser neu gestartet . Sie können es mithilfe von ASP.NET Health Monitoring selbst anzeigen .
Fügen Sie diesen Code einfach zu Ihrer web.config / configuration / system.web hinzu:
Nach dem Auschecken
Windows Log -> Application
. Was ist los:Wenn Sie einen Ordner löschen und ein Unterordner vorhanden ist, wird zuerst der Unterordner gelöscht
Delete(path, true)
. FileChangesMonitor muss über das Entfernen und Herunterfahren Ihrer App informiert sein. Inzwischen ist Ihr Hauptverzeichnis noch nicht gelöscht. Dies ist das Ereignis aus Log:Delete()
hat seine Arbeit nicht beendet und da die App heruntergefahren wird, wird eine Ausnahme ausgelöst:Wenn sich in einem Ordner, den Sie löschen, keine Unterordner befinden, löscht Delete () nur alle Dateien und diesen Ordner. Die App wird ebenfalls neu gestartet, es treten jedoch keine Ausnahmen auf , da der Neustart der App nichts unterbricht. Trotzdem verlieren Sie alle in Bearbeitung befindlichen Sitzungen, die App reagiert beim Neustart nicht auf Anfragen usw.
Was jetzt?
Es gibt einige Problemumgehungen und Optimierungen, um dieses Verhalten zu deaktivieren: Directory Junction , FCN mit Registrierung deaktivieren , FileChangesMonitor mithilfe von Reflection stoppen (da es keine exponierte Methode gibt) , aber alle scheinen nicht richtig zu sein, da FCN für a vorhanden ist Grund. Es kümmert sich um die Struktur Ihrer App , die nicht die Struktur Ihrer Daten ist . Die kurze Antwort lautet: Platzieren Sie Ordner, die Sie löschen möchten, außerhalb Ihrer App. FileChangesMonitor erhält keine Benachrichtigungen und Ihre App wird nicht jedes Mal neu gestartet. Sie erhalten keine Ausnahmen. Um sie im Web sichtbar zu machen, gibt es zwei Möglichkeiten:
Erstellen Sie einen Controller, der eingehende Anrufe verarbeitet und dann Dateien zurückgibt, indem Sie aus einem Ordner außerhalb einer App (außerhalb von wwwroot) lesen.
Wenn Ihr Projekt groß ist und die Leistung am wichtigsten ist, richten Sie einen separaten kleinen und schnellen Webserver für die Bereitstellung statischer Inhalte ein. Auf diese Weise überlassen Sie IIS seinen spezifischen Job. Es kann sich auf demselben Computer (Mungo für Windows) oder einem anderen Computer (Nginx für Linux) befinden. Eine gute Nachricht ist, dass Sie keine zusätzliche Microsoft-Lizenz bezahlen müssen, um einen statischen Inhaltsserver unter Linux einzurichten.
Hoffe das hilft.
quelle
Wie oben erwähnt, schlägt die "akzeptierte" Lösung in Bezug auf Analysepunkte fehl - dennoch wird sie von den Leuten markiert (???). Es gibt eine viel kürzere Lösung, die die Funktionalität ordnungsgemäß repliziert:
Ich weiß, behandelt die später erwähnten Berechtigungsfälle nicht, aber in jeder Hinsicht bietet FAR BETTER die erwartete Funktionalität des ursprünglichen / stock Directory.Delete () - und mit viel weniger Code .
Sie können die Verarbeitung sicher fortsetzen, da das alte Verzeichnis nicht im Weg ist ... auch wenn es nicht weg ist, weil das 'Dateisystem immer noch aufholt' (oder was auch immer MS für die Bereitstellung einer fehlerhaften Funktion entschuldigt hat) .
Wenn Sie wissen, dass Ihr Zielverzeichnis groß / tief ist und nicht warten möchten (oder sich um Ausnahmen kümmern möchten), kann die letzte Zeile durch Folgendes ersetzt werden:
Sie können immer noch sicher weiterarbeiten.
quelle
\\server\C$\dir
und machte es\\server\C$asf.yuw
. Als Ergebnis habe ich eine Fehlermeldung erhalten:Directory.Move()
-Source and destination path must have identical roots. Move will not work across volumes.
Hat einwandfrei funktioniert, nachdem ich Petes Code verwendet habe, AUSSER es werden keine Handles für gesperrte Dateien oder offene Verzeichnisse verwendet, sodass derThreadPool
Befehl nie aufgerufen wird .Dieses Problem kann unter Windows auftreten, wenn sich Dateien in einem Verzeichnis (oder einem beliebigen Unterverzeichnis) befinden, dessen Pfadlänge mehr als 260 Symbole beträgt.
In solchen Fällen müssen Sie
\\\\?\C:\mydir
statt löschenC:\mydir
. Über das Limit von 260 Symbolen können Sie hier lesen .quelle
Ich habe mit dieser tausendjährigen Technik gelöst (Sie können den Thread.Sleep alleine im Fang lassen)
quelle
Wenn das aktuelle Verzeichnis Ihrer Anwendung (oder einer anderen Anwendung) dasjenige ist, das Sie löschen möchten, handelt es sich nicht um einen Zugriffsverletzungsfehler, aber ein Verzeichnis ist nicht leer. Stellen Sie sicher, dass es sich nicht um Ihre eigene Anwendung handelt, indem Sie das aktuelle Verzeichnis ändern. Stellen Sie außerdem sicher, dass das Verzeichnis in keinem anderen Programm geöffnet ist (z. B. Word, Excel, Total Commander usw.). Die meisten Programme werden in das Verzeichnis der zuletzt geöffneten Datei verschoben, was dazu führen würde.
quelle
Bei Netzwerkdateien kann Directory.DeleteHelper (rekursiv: = true) eine IOException verursachen, die durch die Verzögerung beim Löschen der Datei verursacht wird
quelle
Ich denke, dass es eine Datei gibt, die von einem Stream geöffnet ist, von dem Sie nicht wissen, dass ich das gleiche Problem hatte, und das gelöst wurde, indem alle Streams geschlossen wurden, die auf das Verzeichnis verweisen, das ich löschen wollte.
quelle
Dieser Fehler tritt auf, wenn eine Datei oder ein Verzeichnis als verwendet verwendet wird. Es ist ein irreführender Fehler. Überprüfen Sie, ob Explorer- oder Befehlszeilenfenster für ein Verzeichnis in der Baumstruktur oder ein Programm, das eine Datei in dieser Baumstruktur verwendet, geöffnet sind.
quelle
Ich habe eine mögliche Instanz des angegebenen Problems gelöst, als die Methoden asynchron und wie folgt codiert waren:
Mit diesem:
Fazit? Es gibt einen asynchronen Aspekt beim Entfernen des Handles, mit dem die Existenz überprüft wird, mit dem Microsoft nicht sprechen konnte. Es ist, als ob die asynchrone Methode in einer if-Anweisung die if-Anweisung hat, die sich wie eine using-Anweisung verhält.
quelle
Sie müssen keine zusätzliche Methode für die Rekursivität erstellen oder Dateien im Ordner extra löschen. Dies alles geschieht automatisch durch einen Anruf
Details finden Sie hier .
So etwas funktioniert ganz gut:
Wenn Sie true als Variable an die Löschmethode übergeben, werden auch Unterdateien und Unterordner mit Dateien gelöscht.
quelle
Keine der oben genannten Antworten hat bei mir funktioniert. Es scheint, dass meine eigene App verwendet
DirectoryInfo
im Zielverzeichnis dazu geführt hat, dass sie gesperrt blieb.Das Erzwingen der Speicherbereinigung schien das Problem zu beheben, jedoch nicht sofort. Bei Bedarf einige Löschversuche.
Beachten
Directory.Exists
Sie, dass es nach einer Ausnahme verschwinden kann. Ich weiß nicht, warum sich das Löschen für mich verzögert hat (Windows 7 SP1)quelle
GC.Collect
ist a) nur ein schlechter Rat und b) keine ausreichend häufige allgemeine Ursache für gesperrte Verzeichnisse, um hier aufgenommen zu werden. Wählen Sie einfach einen der anderen aus und säen Sie unschuldigen Lesern keine Verwirrungusing
Aussage zu tun , dann:using (DirectoryInfo di = new DirectoryInfo(@"c:\MyDir")) { for (int attempts = 0; attempts < 10; attempts++) { try { if (di.Exists(folder)) { Directory.Delete(folder, true); } return; } catch (IOException e) { Thread.Sleep(1000); } } }
addiere true im zweiten Parameter.
Es wird alles entfernen.
quelle