Question

J'ai un programme de mise à jour qui est tout à fait indépendante de ma demande principale. Je lance la update.exe mettre à jour le app.exe. Pour vérifier si le fichier est utilisé, je le déplacer vers un autre fichier et relevez une erreur si elle est en cours d'utilisation. Si aucun problème, je le renommer se déclarerait en arrière. Au moins c'était mon plan ...

  

Programme principal: app.exe
  Programme de mise à jour: update.exe

Ce programme est utilisé sur le réseau sans fonctionnement des services. Ainsi, les utilisateurs sont en cours d'exécution littéralement l'exe sur le réseau sur Thier machine.

Je dois mettre à jour le app.exe lorsque le update.exe a couru. Pour vérifier si le app.exe était encore en usage, j'enveloppait ce qui suit dans un try / catch pour voir si elle a échoué:

  

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

La chose drôle est, même si le app.exe est en cours d'exécution, le mouvement peut renommer le app.exe.tst sans aucune erreur. Je peux même continuer dans l'application sans aucune erreur.

Je pensais que j'étais hors de mon esprit, donc j'eu un autre regard programmeur à cela et il a vérifié ce que je disais ci-dessus.

Nous avons donc essayé cette Enveloppé dans une prise d'essai:

  

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

Je mets le partage de fichiers comme aucun qui, au moins, je pensais que ce serait, montrer qu'il y avait quelqu'un dans le fichier.

Il reste poursuivi sans aucune erreur.

Quelqu'un sait pourquoi je peux renommer un fichier en cours d'utilisation? Aussi, est-il une meilleure façon de le faire que ce que je fais maintenant?

Merci! Eroc

Était-ce utile?

La solution

Vous pouvez effectuer les opérations suivantes pour vérifier si l'application a d'autres instances en cours d'exécution:

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

Ce qui est une façon plus appropriée de vérifier si l'application est en cours d'exécution.

Jetez un oeil à File.Move documentation MSDN. Il détaille les exceptions sont jetés. Vous êtes autorisé à renommer un fichier EXE même si elle est en cours d'utilisation dans Vista.

Autres conseils

Le même code à l'aide "en utilisant":)

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

Ce que vous pouvez faire est de remplacer l'application cible avec un gardien exe.

Ce gardien engendre alors l'application cible, mais crée également un fichier verrouillé dans un emplacement partagé. Le verrou est libéré et le fichier est supprimé lorsque la sortie de l'application.

Alors, avant de mettre à jour le app.exe, vous vérifiez qu'il y a des fichiers verrouillés dans l'emplacement partagé, si des fichiers verrouillés alors le app.exe est utilisé.

Le programme intérimaire pourrait être une application de fenêtre moins, l'application de la console suivante fait à peu près ce qu'il doit faire

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");
    }
}

Le updater recherche alors tous les « AppLock_ * » fichiers, et tente de les ouvrir avec un verrou d'écriture, si elle ne peut pas obtenir un verrou en écriture sur l'un d'eux, l'exe est utilisé.

Hope this helps.

est ce que je fini par faire. L'analyse du réseau ne fonctionne pas sur un réseau peer-to-peer. Il n'a pas résolu les autres ordinateurs du tout.

Quoi qu'il en soit, la voici:

  

Private Sub CheckFileIfFileIsInUse (ByVal thefilename As String)
        Essayez
            'Sur Vista OS, vous pouvez renommer un fichier qui est utilisé
            'The' utilisation du fichier original suit le nouveau nom de fichier

      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

Hope this helps la personne suivante.

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top