Ich bin gespannt, ob dies irgendwelche WTF-Reflexe auslöst. Ich habe einen Prozess, der ein PDF-Dokument aus einer Konsolenanwendung erstellt und anschließend startet. Ich hatte jedoch mit einer Schwachstelle zu kämpfen, bei der, wenn der Benutzer den Prozess mehrmals ausführt und dabei dieselbe Datei erzeugt, ohne die zuvor erzeugte Datei zu schließen, die Anwendung eine Ausnahme auslöst und stirbt. Dies trat relativ häufig auf, da die Dateinamen auf den Nummern der Verkaufsangebote basieren.
Anstatt auf so unschöne Weise zu scheitern, entschied ich mich, auf die automatische Versionserhöhung der Dateien zu setzen:
private static string WriteFileToDisk(byte[] data, string fileName, int version = 0)
{
try
{
var versionExtension = version > 0 ? $"_{version:000}" : string.Empty;
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{fileName}{versionExtension}.pdf");
using (var writer = new FileStream(filePath, FileMode.Create))
{
writer.Write(data, 0, data.Length);
}
return filePath;
}
catch (IOException)
{
return WriteFileToDisk(data, fileName, ++version);
}
}
Wahrscheinlich kann man sich etwas mehr Mühe geben mit der catch
Block, um sicherzustellen, dass ich die richtige(n) IOException(s) abfange. Ich werde wahrscheinlich auch den App-Speicher beim Start löschen, da diese Dateien sowieso temporär sein sollen.
Mir ist klar, dass dies über den Rahmen der Frage des Auftraggebers hinausgeht, einfach zu prüfen, ob die Datei in Gebrauch ist, aber das war in der Tat das Problem, das ich lösen wollte, als ich hier ankam, so dass es vielleicht für jemand anderen nützlich ist.
35 Stimmen
Sie können dies testen, indem Sie alle offenen Handles auf dem System untersuchen. Da es sich bei Windows jedoch um ein Multitasking-Betriebssystem handelt, besteht die Möglichkeit, dass direkt nach der Ausführung des Codes, mit dem festgestellt werden soll, ob die Datei geöffnet ist, ein Prozesscode mit der Verwendung dieser Datei beginnt und zu dem Zeitpunkt, zu dem Sie versuchen, sie zu verwenden, ein Fehler auftritt. Es ist jedoch nicht verkehrt, zuerst zu prüfen, ob die Datei geöffnet ist; gehen Sie nur nicht davon aus, dass sie nicht verwendet wird, wenn Sie sie tatsächlich benötigen.
6 Stimmen
Aber gerade für dieses spezielle Problem würde ich empfehlen, die Dateihandles nicht zu untersuchen und nur eine bestimmte Anzahl von Versuchen durchzuführen, z. B. 3-5, bevor sie fehlschlagen.
0 Stimmen
Wie wird diese Bilddatei erstellt? Können Sie Ihr Programm anhalten/schlafen/pausieren, bis die Erzeugung abgeschlossen ist? Das ist bei weitem der bessere Weg, um die Situation zu bewältigen. Wenn nicht, dann glaube ich nicht, dass Sie eine Ausnahmebehandlung vermeiden können.
0 Stimmen
Ist nicht jede Verwendung von Ausnahmen eine Überprüfung einer Annahme, indem man etwas potenziell Gefährliches tut und dabei absichtlich die Möglichkeit eines Fehlschlags nicht ausschließt?
40 Stimmen
Ihre Philosophie hat ein schlechtes Verständnis von Ausnahmen. Die meisten Leute denken, Ausnahmen bedeuten heilige Scheiße-aus-dem-Doom-irgendetwas-ist-falsch-die-die-die. Wenn Ausnahme bedeutet.... Ausnahme. Es bedeutet, dass etwas Außergewöhnliches passiert ist, das Sie "behandeln" (oder berücksichtigen) müssen. Vielleicht wollen Sie den Datenzugriff immer wieder versuchen, vielleicht muss der Benutzer wissen, dass Sie keine Verbindung herstellen können. Was tun Sie dann? Sie behandeln die ConnectionFailedException und benachrichtigen den Benutzer, so dass er vielleicht nach einer Stunde aufhört, es zu versuchen, und bemerkt, dass das Kabel ausgesteckt ist.
0 Stimmen
Warum die Prüfung und Verarbeitung in verschiedenen Prozeduren? try {open file in FileShare.None; process file; close file} catch {filelocked) {///locked, we'll get it next time}
2 Stimmen
Lee Louviere hat eine berechtigte Abneigung dagegen, mit Ausnahmen zu arbeiten. Wenn man mit der filexists-Methode leicht herausfinden kann, ob eine Datei existiert, gibt es dann einen ähnlichen Befehl, um herauszufinden, ob die Datei, mit der man arbeiten möchte, in Gebrauch ist? Ich glaube, das ist die eigentliche Frage, die der Benutzer stellt.
1 Stimmen
@webs Manche Ausnahmen sind einfach eine Tatsache. Die Verwendung von File.Exists() ist gut, aber wie die Antwort sagt, ist es nicht immer möglich, sie zu vermeiden. Zum Beispiel könnte eine Datei zwischen dem Zeitpunkt, an dem Sie prüfen, ob sie existiert, und dem Zeitpunkt, an dem Sie sie tatsächlich öffnen, existieren. Diese unbestimmte Zeitspanne ist in den meisten Fällen gut genug, aber es gibt keine Garantien und daher sollte ein Exception-Handler den Aufruf zum Öffnen der Datei einschließen usw.
1 Stimmen
@webs Wenn Sie leicht filexists Methode verwenden können, um zu wissen, ob eine Datei vorhanden ist, was ähnlichen Befehl vorhanden ist, um zu wissen, ob die Datei, die Sie mit arbeiten möchten, in Gebrauch ist? Ich bin etwas spät dran, aber diese beiden Beispiele sind TOCTOU-Wanzen . Die Ergebnisse sind sofort ungültig. "Check-then-do" ist nutzlos - der "Check" kann nicht mit dem "Do" identisch sein, so dass der "Check" aus unterschiedlichen Gründen fehlschlagen oder erfolgreich sein kann, wenn der "Do" fehlschlagen würde. Wenn Sie eine Datei öffnen müssen DATEI ÖFFNEN . Nichts anderes kann Ihnen einen endgültigen Beweis dafür liefern, dass die Öffnung funktionieren wird.
2 Stimmen
Was ist, wenn ich nicht herausfinden möchte, ob ich überhaupt in eine Datei schreiben KANN, sondern ob ich lieber nicht schreiben sollte, obwohl ich es könnte, weil jemand anderes gerade an derselben Datei arbeitet?