2 Stimmen

VB.Net 3.5 Prüfen, ob Datei in Gebrauch ist

Ich habe ein Aktualisierungsprogramm, das völlig unabhängig von meiner Hauptanwendung ist. Ich führe die update.exe aus, um die app.exe zu aktualisieren. Um zu prüfen, ob die Datei verwendet wird, verschiebe ich sie in eine andere Datei und erhalte eine Fehlermeldung, wenn sie verwendet wird. Wenn keine Probleme auftreten, benenne ich sie wieder um. Zumindest war das mein Plan...

Hauptprogramm: app.exe
Programm aktualisieren: update.exe

Dieses Programm wird über das Netzwerk verwendet, ohne dass irgendwelche Dienste laufen. Der Benutzer führt also buchstäblich die Exe über das Netzwerk auf seinem Rechner aus.

Ich muss die app.exe aktualisieren, wenn die update.exe ausgeführt wurde. Um zu überprüfen, ob die app.exe noch in Gebrauch war, wickelte ich das folgende in ein Try/Catch, um zu sehen, wenn es fehlgeschlagen ist:

IO.File.Move(upddir & " \app.exe ", upddir & " \app.exe.tst ")
IO.File.Move(upddir & " \app.exe.tst ", upddir & " \app.exe ")

Das Seltsame ist, dass selbst wenn die app.exe ausgeführt wird, der Umzug sie in app.exe.tst umbenennen kann, ohne dass ein Fehler auftritt. Ich kann sogar in der Anwendung ohne Fehler weitermachen.

Ich dachte, ich hätte den Verstand verloren, also ließ ich einen anderen Programmierer einen Blick darauf werfen, und er bestätigte, was ich oben sagte.

Also haben wir dies in einem Try-Catch versucht:

Dim readfile As New FileStream(upddir & " \app.exe ", FileMode.Open, FileAccess.Read, FileShare.None)
readfile.Dispose()

Ich habe die Dateifreigabe als keine angegeben, die, so dachte ich zumindest, zeigen würde, dass sich jemand in der Datei befindet.

Der Vorgang wurde dennoch ohne Fehler fortgesetzt.

Weiß jemand, warum ich eine in Gebrauch befindliche Datei umbenennen kann? Gibt es eine bessere Möglichkeit, als das, was ich jetzt tue?

Danke! Eroc

7voto

Manuel Alves Punkte 3533

Derselbe Code mit "using" :)

Public Function FileInUse(ByVal sFile As String) As Boolean
 Dim thisFileInUse As Boolean = False
 If System.IO.File.Exists(sFile) Then
     Try
       Using f As New IO.FileStream(sFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
                ' thisFileInUse = False
       End Using
     Catch
       thisFileInUse = True
     End Try
 End If
 Return thisFileInUse
End Function

1voto

James Punkte 77534

Sie können wie folgt vorgehen, um zu prüfen, ob die Anwendung weitere Instanzen hat:

Process.GetProcessesByName("app.exe", "Machine1").Length > 0

Dies ist ein geeigneterer Weg, um zu überprüfen, ob die Anwendung läuft.

Werfen Sie einen Blick auf Datei.Verschieben MSDN-Dokumentation. Sie beschreibt, welche Ausnahmen ausgelöst werden. Sie dürfen eine Exe umbenennen, auch wenn sie unter Vista in Gebrauch ist.

0voto

Binary Worrier Punkte 49250

Sie könnten die Zielanwendung durch eine Caretaker-Exe ersetzen.

Dieser Caretaker startet dann die Zielanwendung, erstellt aber auch eine gesperrte Datei an einem gemeinsamen Speicherort. Die Sperre wird aufgehoben und die Datei wird gelöscht, wenn die Anwendung beendet wird.

Bevor Sie dann die app.exe aktualisieren, prüfen Sie, ob es gesperrte Dateien am gemeinsamen Speicherort gibt; wenn dies der Fall ist, wird die app.exe verwendet.

Das Hausmeisterprogramm könnte eine fensterlose Anwendung sein, die folgende Konsolenanwendung tut ziemlich genau das, was sie tun muss

class Program
{
    static string lockFileName;
    static System.IO.StreamWriter lockFileWrtier;
    static void Main(string[] args)
    {
        lockFileName = "AppLock_" + System.IO.Path.GetRandomFileName();

        lockFileWrtier = new System.IO.StreamWriter(lockFileName);

        System.Diagnostics.Process p = new Process();
        p.StartInfo.FileName = "cmd.exe";
        p.EnableRaisingEvents = true;
        p.Exited += new EventHandler(p_Exited);

        p.Start();

        Console.WriteLine("Press any key to stop");
        Console.ReadKey();
    }

    static void p_Exited(object sender, EventArgs e)
    {
        lockFileWrtier.Dispose();
        System.IO.File.Delete(lockFileName);

        Console.WriteLine("Process has exited");
    }
}

Der Updater sucht dann nach allen "AppLock_*"-Dateien und versucht, sie mit einer Schreibsperre zu öffnen; wenn er keine Schreibsperre für eine dieser Dateien erhalten kann, ist die Exe in Gebrauch.

Ich hoffe, das hilft.

0voto

ErocM Punkte 319

Das habe ich dann auch gemacht. Der Netzwerkscan funktionierte in einem Peer-to-Peer-Netzwerk nicht. Er hat die anderen Computer überhaupt nicht aufgelöst.

Wie auch immer, hier ist es:

Private Sub CheckFileIfFileIsInUse(ByVal thefilename As String)
Versuchen Sie
' auf dem Vista-Betriebssystem können Sie eine verwendete Datei umbenennen
dem neuen Dateinamen folgt das 'in use' der Originaldatei

      Dim testfile As String = thefilename & ".tst"<br />

      If IO.File.Exists(testfile) Then<br />
          IO.File.Delete(testfile)<br />
      End If<br />

      ' so we have to rename it to something else<br />
      IO.File.Move(thefilename, testfile)<br />

      ' copy it back to the original file name in case something <br />breaks 
      ' this just keeps them in working order if it does<br />
      IO.File.Copy(testfile, thefilename)<br />

      ' then we try to delete the original file that could be in use <br />
      ' which will return an 'in use' error at this point<br />
      If IO.File.Exists(testfile) Then<br />
          IO.File.Delete(testfile)<br />
      End If<br />

  Catch ex As Exception<br />
      'throw it to the originating method<br />
      Throw<br />
  End Try<br />

End Sub

Ich hoffe, das hilft der nächsten Person.

0voto

Destek Punkte 1
Public Function FileInUse(ByVal sFile As String) As Boolean
    If System.IO.File.Exists(sFile) Then
        Try
            Dim F As Short = FreeFile()
            FileOpen(F, sFile, OpenMode.Binary, OpenAccess.ReadWrite, OpenShare.LockReadWrite)
            FileClose(F)
        Catch
            Return True
        End Try
    End If
End Function

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