987 Stimmen

Gibt es eine Möglichkeit zu überprüfen, ob eine Datei in Gebrauch ist?

Ich schreibe ein Programm in C#, das wiederholt auf 1 Bilddatei zugreifen muss. Die meiste Zeit funktioniert es, aber wenn mein Computer schnell läuft, wird es versuchen, auf die Datei zuzugreifen, bevor es zurück in das Dateisystem gespeichert wurde und einen Fehler ausgeben:

"Datei wird von einem anderen Prozess verwendet"

Ich würde gerne einen Weg finden, dies zu umgehen, aber alles, was ich gegoogelt habe, hat nur die Erstellung von Prüfungen mit Hilfe der Ausnahmebehandlung ergeben. Dies ist gegen meine Religion, so ich frage mich, ob jemand einen besseren Weg, es zu tun hat?

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.

5voto

Bernhard Punkte 2281

Abgesehen von funktionierenden 3-Linern und nur als Referenz: Wenn Sie die in voller Blüte Informationen - es gibt ein kleines Projekt im Microsoft Dev Center:

https://code.msdn.microsoft.com/windowsapps/How-to-know-the-process-704839f4

Jetzt zu finden unter: https://github.com/TacticalHorse/LockFinder/blob/master/LockFinder.cs

Aus der Einleitung:

Der C#-Beispielcode, der in .NET Framework 4.0 entwickelt wurde, hilft bei der herauszufinden, welcher Prozess eine Sperre für eine Datei hat. RmStartSession Funktion, die in rstrtmgr.dll enthalten ist, wurde verwendet, um eine Restart-Manager-Sitzung zu erstellen, und je nach Rückgabe Ergebnis wird eine neue Instanz des Win32Exception-Objekts erstellt. Nach Registrierung der Ressourcen in einer Restart-Manager-Sitzung über RmRegisterRescources Funktion, RmGetList Funktion wird aufgerufen, um zu prüfen welche Anwendungen eine bestimmte Datei verwenden, indem sie die die RM_PROCESS_INFO Array.

Es funktioniert durch die Verbindung mit der "Restart Manager Session".

Der Restart Manager verwendet die Liste der mit der Sitzung registrierten Ressourcen, um um festzustellen, welche Anwendungen und Dienste heruntergefahren und neu gestartet werden müssen. Ressourcen können durch Dateinamen, Dienstkurznamen oder RM_UNIQUE_PROCESS-Strukturen die laufende Anwendungen beschreiben.

Es könnte ein wenig sein overengineered für Ihre besonderen Bedürfnisse... Aber wenn es das ist, was usted wollen, nehmen Sie sich das vs-projekt vor.

4voto

Luke Schafer Punkte 9113

Die einzige Möglichkeit, die ich kenne, ist die Verwendung der Win32-API für exklusive Sperren, die nicht sehr schnell ist, aber es gibt Beispiele.

Die meisten Menschen, für eine einfache Lösung für diese, einfach zu versuchen / fangen / schlafen Schleifen.

3voto

atlaste Punkte 29028

Meiner Erfahrung nach möchte man dies in der Regel tun, dann seine Dateien "schützen", um etwas Ausgefallenes zu tun, und dann die "geschützten" Dateien verwenden. Wenn Sie nur eine Datei haben, die Sie auf diese Weise verwenden wollen, können Sie den Trick anwenden, der in der Antwort von Jeremy Thompson erklärt wird. Wenn Sie jedoch versuchen, dies mit vielen Dateien zu tun (z. B. wenn Sie ein Installationsprogramm schreiben), werden Sie ziemlich viel Ärger bekommen.

Eine sehr elegante Lösung für dieses Problem ist die Tatsache, dass Ihr Dateisystem es nicht zulässt, einen Ordnernamen zu ändern, wenn eine der darin enthaltenen Dateien bereits verwendet wird. Behalten Sie den Ordner im gleichen Dateisystem, und es wird wie ein Zauber funktionieren.

Bitte beachten Sie, dass Sie sich der offensichtlichen Möglichkeiten bewusst sein sollten, wie dies ausgenutzt werden kann. Immerhin werden die Dateien nicht gesperrt. Beachten Sie auch, dass es andere Gründe gibt, die dazu führen können, dass Ihre Move Operation scheitert. Natürlich kann eine angemessene Fehlerbehandlung (MSDN) hier helfen.

var originalFolder = @"c:\myHugeCollectionOfFiles"; // your folder name here
var someFolder = Path.Combine(originalFolder, "..", Guid.NewGuid().ToString("N"));

try
{
    Directory.Move(originalFolder, someFolder);

    // Use files
}
catch // TODO: proper exception handling
{
    // Inform user, take action
}
finally
{
    Directory.Move(someFolder, originalFolder);
}

Für einzelne Dateien würde ich mich an den von Jeremy Thompson gemachten Vorschlag halten, die Dateien zu sperren.

3voto

Ich musste einmal PDFs in ein Online-Backup-Archiv hochladen. Die Sicherung schlug jedoch fehl, wenn der Benutzer die Datei in einem anderen Programm (z. B. PDF Reader) geöffnet hatte. In meiner Eile habe ich einige der Top-Antworten in diesem Thread ausprobiert, konnte sie aber nicht zum Laufen bringen. Was bei mir funktioniert hat, war der Versuch, die PDF-Datei nach ein eigenes Verzeichnis . Ich habe festgestellt, dass dies fehlschlägt, wenn die Datei in einem anderen Programm geöffnet ist, und wenn die Verschiebung erfolgreich war, ist kein Wiederherstellungsvorgang erforderlich, wie es der Fall wäre, wenn die Datei in ein anderes Verzeichnis verschoben würde. Ich möchte meine grundlegende Lösung hier veröffentlichen, falls sie für die spezifischen Anwendungsfälle anderer nützlich sein könnte.

string str_path_and_name = str_path + '\\' + str_filename;
FileInfo fInfo = new FileInfo(str_path_and_name);
bool open_elsewhere = false;
try
{
    fInfo.MoveTo(str_path_and_name);
}
catch (Exception ex)
{
    open_elsewhere = true;
}

if (open_elsewhere)
{
    //handle case
}

2voto

Tomasz Żmuda Punkte 609

Sie können meine Bibliothek für den Zugriff auf Dateien aus mehreren Anwendungen verwenden.

Sie können es über Nuget installieren: Install-Package Xabe.FileLock

Wenn Sie weitere Informationen darüber wünschen, besuchen Sie https://github.com/tomaszzmuda/Xabe.FileLock

ILock fileLock = new FileLock(file);
if(fileLock.Acquire(TimeSpan.FromSeconds(15), true))
{
    using(fileLock)
    {
        // file operations here
    }
}

fileLock.Acquire-Methode wird nur true zurückgeben, wenn Datei exklusiv für dieses Objekt sperren kann. Aber app, die Datei hochladen muss es in Dateisperre zu tun. Wenn das Objekt unzugänglich ist, gibt die Methode false zurück.

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