Gibt es eine Möglichkeit zu überprüfen, ob eine Datei in Benutzung ist?
Ich Schreibe ein Programm in C# und muss wiederholt Zugang 1-image-Datei. Die meisten der Zeit es funktioniert, aber wenn mein computer schnell laufen, es wird versucht, auf die Datei zugreifen, bevor es gespeichert wurde wieder auf das Dateisystem und wirft einen Fehler: "Datei von einem anderen Prozess verwendet".
Ich würde gerne einen Weg finden, um dieses, aber alle meine Googlen hat nur nachgegeben erstellen von Prüfungen durch die Verwendung von exception-handling. Das ist gegen meine religion, ich Frage mich, wenn jemand eine bessere Weise, es zu tun?
- Klar, Sie können es testen, indem Sie untersuchen alle geöffneten handles auf dem system. Jedoch da Windows ist ein multitasking-Betriebssystem, es gibt eine chance, dass sofort, nachdem Sie den code ausführen, um festzustellen, ob die Datei geöffnet ist und Sie meinen, es ist nicht ein Prozess von code beginnen mit die Datei, die dann durch die Zeit, die Sie versuchen, es zu verwenden, erhalten Sie eine Fehlermeldung. Aber, es ist nichts falsch mit der überprüfung den ersten, nur nicht davon ausgehen, es ist nicht in verwenden Sie, wenn Sie es wirklich benötigen.
- Aber nur für dieses spezifische Problem; ich würde empfehlen, nicht die Prüfung des Datei-handles, und nur versuchen, einige voreingestellte Anzahl von Zeiten, sagen 3-5 vor dem scheitern.
- Wie ist diese image-Datei erzeugt? Können Sie stop/schlafen/pause Ihr Programm, bis die Generierung abgeschlossen ist? Das ist bei weitem eine überlegene Art mit der situation umzugehen. Wenn nicht, dann denke ich nicht, dass Sie können, vermeiden Sie die Verwendung von exception-handling.
- Dies ist ein Duplikat von stackoverflow.com/questions/1304/...
- Nicht alle die Nutzung von Ausnahmen, die eine überprüfung auf eine Annahme von etwas potenziell gefährlich ist und absichtlich nicht ausschließt, die Möglichkeit des Scheiterns?
- Ihre Philosophie hat ein schlechtes Verständnis von Ausnahmen. Die meisten Leute denken, dass Ausnahmen die Mittel Heiligen-Mist-out-of-doom-irgendwas-ist-falsch-sterben-sterben-sterben. Als Ausnahme bedeutet..... Ausnahme. Es bedeutet, dass etwas außergewöhnliches geschehen ist, dass Sie brauchen, um zu "verarbeiten" (oder-Konto für). Vielleicht wollen Sie auf halten, wiederholen für den Datenzugriff, vielleicht muss der Benutzer wissen, dass Sie keine Verbindung herstellen können. Was tun Sie? Sie behandeln die ConnectionFailedException und dem Nutzer mitteilen, so vielleicht, Sie werden aufhören zu versuchen, nach einer Stunde, und beachten Sie die Kabel nicht angeschlossen ist.
- Mehr potentielle Antworten hier: stackoverflow.com/questions/1304/how-to-check-for-file-lock
- Spolier alert; nicht einen konstruktiven Kommentar; aber das format der Frage-und die Kommentare sind einfach genial.
- Warum haben die Prüfung und Bearbeitung in den verschiedenen Verfahren? try {open Datei im FileShare.Keine; Prozess-Datei; Datei schließen} catch {filelocked) {//gesperrt ist, bekommen wir es das nächste mal}
- Lee Louviere der op hat eine gültige Abneigung gegen das arbeiten mit Ausnahmen. Wenn Sie einfach verwenden können filexists Methode wissen, ob eine Datei vorhanden ist, was einen ähnlichen Befehl existiert, um zu wissen, ob die Datei, die Sie möchten, mit zu arbeiten ist im Einsatz? In der Tat glaube ich, dass ist die Frage die op ist wirklich zu Fragen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Aktualisiert HINWEIS auf diese Lösung: Prüfung mit
FileAccess.ReadWrite
Fehler für Nur-Lese-Dateien, so dass die Lösung wurde geändert, um zu überprüfen, mitFileAccess.Read
. Obwohl diese Lösung funktioniert, weil die versuchen zu prüfen, mitFileAccess.Read
fehl, wenn die Datei hat eine Schreib-oder Lesesperre auf es, aber diese Lösung wird nicht funktionieren, wenn die Datei nicht Schreib-oder Lese-Sperre auf es, D. H. es wurde geöffnet (gelesen oder schreiben) mit FileShare.Lesen oder FileShare.Schreibzugriff.ORIGINAL:
Ich habe diesen code für die Vergangenheit einige Jahre, und ich habe keine Probleme mit ihm.
Verstehe Ihre Bedenken über die Verwendung von Ausnahmen, aber Sie können nicht vermeiden, dass Sie alle von der Zeit:
public static bool IsLocked(this FileInfo file) {/*...*/}
.using
block mit nichts zu tun, der stream würde dazu führen, dass einige seltsame code in diesem Fall. Obwohl ich Neige dazu, verwenden Sie immerusing
aufIDisposable
ich denke, dieser Fall ist so mehr lesbar, ohne eineusing
.virtual
, nichtstatic
?Können Sie leiden aus einem thread von race-Bedingung, die auf der es gibt dokumentierte Beispiele von diesen verwendet wird, wie eine Sicherheitslücke. Wenn Sie überprüfen, dass die Datei verfügbar ist, aber dann versuchen Sie es und verwenden Sie es werfen könnte an diesem Punkt, die ein böswilliger Benutzer könnte zu zwingen und auszubeuten in Ihrem code.
Ihre beste Wette ist ein try-catch /finally-das versucht, die Datei-handle.
try
blockieren, wodurch die race condition, wo ein anderer Prozess kann die Datei sperren, zwischen den check-in und öffnen - denn die überprüfen und zu öffnen, ist ein atomarer Vorgang hier.using
Blöcke verwendet werden sollte, 99,9% der Zeit für etwas Implementierung von IDisposable. Wie Sie scheinen zu wissen:using
Blöcke ziemlich einfach IL unten, um einen try/finally-mit einem x.Dispose () - Aufruf. Aber das beinhaltet noch nicht einfangen und die Behandlung von Ausnahmen. So das ein oder so Zeilen code, die vielleicht tatsächlich benötigen handling (die FileStream-Datei mit.Öffnen Sie in diesem Fall) sollten verpackt werden, um zu fangen. Brechen Sie die Verwendung in einem benutzerdefinierten try/catch/finally-fügt Geruch.Verwenden, um zu überprüfen, ob eine Datei gesperrt ist:
Aus performance-Gründen empfehle ich Ihnen, Lesen Sie den Inhalt der Datei in dem gleichen Betrieb. Hier sind einige Beispiele:
Probieren Sie es selbst:
IOException
statt auf AllgemeineException
und dann ein test auf Typ.IOException
nach den Allgemeinen. Die Allgemeinen fangen alles vorbei und die spezifischenIOException
wird immer einsam sein. Nur tauschen die beiden.FileAccess fileAccess = FileAccess.Read, FileShare fileShare = FileShare.ReadWrite
GetHRForException
hat Nebenwirkungen - ab .NET 4.5 dieHResult
Eigenschaft ist öffentlich.fileStream.Close();
. Ist es wirklich ein Fall oder eine race condition, wo dieser wird einen Effekt haben?Vielleicht könnten Sie verwenden ein FileSystemWatcher und achten Sie auf das Changed-Ereignis.
Ich habe nicht verwendet diese selbst, aber es könnte sein, lohnt sich ein Schuss. Wenn die filesystemwatcher-stellt sich heraus, um ein bisschen heavy für diesen Fall, würde ich für den try/catch/sleep-Schleife.
Verwenden Sie einfach die Ausnahme als gedacht. Akzeptieren Sie, dass die Datei in Gebrauch ist und versuchen Sie es erneut, immer wieder, bis Sie Ihre Aktion abgeschlossen ist. Dies ist auch der effizienteste, weil Sie verschwenden Sie keine Zyklen prüfen den Zustand, bevor Sie handeln.
Verwenden Sie die Funktion beispielsweise für folgenden
Wiederverwendbare Methode, die mal nach 2 Sekunden
die einzige Möglichkeit, die ich kenne, ist die Verwendung der Win32-exclusive-lock-API, die nicht allzu schnelle, aber Beispiele vorhanden.
Meisten Menschen, für eine einfache Lösung, einfach try/catch/schlafen Schleifen.
Hoffe, das hilft!
Können Sie wieder eine Aufgabe, die Ihnen ein Strom, sobald Sie verfügbar sind. Es ist eine einfache Lösung, aber es ist ein guter Ausgangspunkt. Es ist thread-sicher.
Können diesen stream wie gewohnt:
GetStreamAsync()
?Akzeptierten Antworten über leiden, ein Problem, wo, wenn die Datei geöffnet wurde, die für das schreiben mit einem FileShare.Lese-Modus oder, wenn die Datei ein Nur-Lese-Attribut wird der code nicht funktionieren. Diese modifizierte Lösung arbeitet höchst zuverlässig, mit zwei Dinge im Auge zu behalten (gilt für die akzeptierte Lösung auch):
Halten die oben genannten im Verstand, diese überprüft, ob die Datei entweder gesperrt zum schreiben oder gesperrt, um zu verhindern, dass Lesen:
Abgesehen von arbeiten 3-Liner und nur als Referenz: Wenn Sie möchten, dass die ausgewachsenen Informationen - es ist ein kleines Projekt auf Microsoft Dev Center:
https://code.msdn.microsoft.com/windowsapps/How-to-know-the-process-704839f4
Aus der Einleitung:
Es funktioniert durch den Anschluss an die "Restart-Manager-Sitzung".
Ist es vielleicht ein wenig overengineered für Ihre besonderen Bedürfnisse...
Aber wenn es das ist, was Sie möchten, gehen Sie voran und ergreifen Sie das vs-Projekt.
Hier ist etwas code, wie ich das am besten sagen, macht das gleiche wie die akzeptierte Antwort, aber mit weniger code:
Aber ich denke, es ist robuster, es zu tun, in der folgenden Weise:
Können Sie meine Bibliothek für den Zugriff auf Dateien von mehreren apps.
Können Sie es von nuget: Install-Package Xabe.FileLock
Wenn Sie wollen mehr Informationen über Sie zu überprüfen
https://github.com/tomaszzmuda/Xabe.FileLock
fileLock.Erwerben, die Methode gibt true zurück, nur wenn können die lock-Datei ist exklusiv für dieses Objekt.
Aber app, die Upload-Datei muss in die Datei zu sperren.
Wenn das Objekt nicht zugänglich ist metod false zurück.
In meiner Erfahrung, werden Sie in der Regel wollen, um dies zu tun, und dann zu 'schützen' Ihre Dateien zu tun, etwas ausgefallenes und verwenden Sie dann die "geschützten" Dateien. Wenn Sie nur eine Datei, die Sie verwenden möchten, wie diese, können Sie den trick, der erklärt, in der Antwort von Jeremy Thompson. Allerdings, wenn Sie versuchen, tun dies auf sehr viele Dateien (sagen wir, zum Beispiel, wenn Sie schreiben eine installer), sind Sie in für ein bisschen weh.
Einen sehr eleganten Weg, dieses Problem kann gelöst werden durch Verwendung der Tatsache, dass Ihre Datei-system wird nicht zulassen, dass Sie einen Ordner-Namen ändern, wenn eine der Dateien, die es verwendet wird. Halten Sie die Ordner in der selben Datei-system und es funktioniert wie ein Charme.
Tun, beachten Sie, dass Sie sollten sich bewusst sein, die offensichtlichen Möglichkeiten, wie diese genutzt werden können. Nachdem alle, die Dateien nicht gesperrt werden. Beachten Sie auch, dass es andere Gründe können dazu führen, dass Ihre
Move
operation scheitern. Offensichtlich ordnungsgemäße Fehlerbehandlung (MSDN) können hier helfen.Für einzelne Dateien würd ich mich mit der Verriegelung Vorschlag gepostet von Jeremy Thompson.
FileShare
und Prüfung für ein Schloss.Ich bin daran interessiert zu sehen, ob dies löst jede WTF Reflexe. Ich habe einen Prozess erstellt und anschließend startet ein PDF-Dokument aus einer console app. Ich war jedoch der Umgang mit Gebrechlichkeit, wo, wenn der Benutzer führen den Prozess mehrere Male, so dass die gleiche Datei, ohne Sie zuerst schließen Sie die zuvor generierte Datei, die app würde eine exception werfen und sterben. Dies war ein Recht häufiges auftreten, weil die Datei-Namen basieren auf Angebot zahlen.
Anstatt versagt in so einem unvermittelten Weise, habe ich beschlossen, verlassen Sie sich auf auto-increment Datei-Versionierung:
Wohl etwas mehr Sorgfalt kann auf die
catch
- block, um sicherzustellen, dass ich bin, fangen die richtigen IOException(s). Ich werde wohl auch klar aus dem app-Speicher auf startup, da diese Dateien dienen der temporären sowieso.Ich weiß, das geht über den Umfang der OP die Frage einfach zu überprüfen, ob die Datei ist in Verwendung, aber das war ja das problem, ich war auf der Suche zu lösen, wenn ich hier angekommen, so ist es vielleicht für jemanden nützlich sein.
Würde so etwas helfen?
Versuchen und verschieben/kopieren Sie die Datei in ein temp-dir. Wenn Sie können, es hat keine Sperre und Sie können sicher arbeiten im temp-dir, ohne sich zu sperren. Sonst einfach versuchen zu bewegen, es wieder in x Sekunden.
Ich diese Problemumgehung verwenden, aber ich habe eine Zeit zwischen, wenn ich die Datei sperren mit IsFileLocked Funktion und wenn ich die Datei öffnen. In dieser Zeitspanne einige andere Threads können die Datei öffnen, also werde ich bekommen IOException.
So, ich habe extra code für diese. In meinem Fall möchte ich laden XDocument:
Was denkst du? Kann ich das ändern, was? Vielleicht habe ich nicht IsFileBeingUsed Funktion überhaupt?
Dank