Domanda

Ho un programma di aggiornamento che è completamente indipendente dalla mia principale dell'applicazione. Corro l'update.exe per aggiornare l'app.exe. Per verificare se il file è in uso, lo sposto in un altro file e prendere un errore se è in uso. Se nessun problema occurr rinomino indietro. Almeno questo era il mio piano ...

  

Programma principale:
app.exe   Programma di aggiornamento: update.exe

Questo programma viene utilizzato attraverso la rete senza prestazioni in esecuzione. Così, gli utenti sono letteralmente in esecuzione il file EXE in rete sul loro macchina.

Ho bisogno di aggiornare l'app.exe quando l'update.exe ha eseguito. Per verificare se l'app.exe era ancora in uso stavo avvolgendo la segue in un try / catch per vedere se non è riuscito:

  

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

La cosa divertente è, anche se l'app.exe è in esecuzione, la mossa può rinominarlo al app.exe.tst senza alcun errore. Posso anche continuare nell'applicazione senza errori.

Ho pensato che ero fuori di testa, così ho avuto un altro sguardo programmatore a questo e ha verificato quello che ho detto sopra.

Quindi, abbiamo provato questo avvolto in un tentativo di cattura:

  

readfile fioco come nuovo FileStream (upddir & "\ app.exe", FileMode.Open, FileAccess.Read, FileShare.NONE)
  readfile.Dispose ()

Ho messo la condivisione file come nessuno che, almeno ho pensato che sarebbe, mostrano che c'era qualcuno nel file.

Si continuava senza alcun errore.

Qualcuno sa il motivo per cui posso rinominare un file in uso? Inoltre, c'è un modo migliore per farlo che quello che sto facendo ora?

Grazie! Eroc

È stato utile?

Soluzione

Si potrebbe fare quanto segue per verificare se l'applicazione ha altre istanze in esecuzione:

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

che è un modo più appropriato di verificare se l'applicazione è in esecuzione.

Dai un'occhiata alla File.Move documentazione MSDN. E 'dettagli quali eccezioni sono gettati. Hai il permesso di rinominare un file exe, anche se è in uso in Vista.

Altri suggerimenti

Lo stesso codice utilizzando "utilizzando":)

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

Che cosa si potrebbe fare è sostituire l'applicazione di destinazione con un exe custode.

Questa custode quindi genera l'applicazione di destinazione, ma crea anche un file bloccato in una posizione condivisa. Il blocco viene rilasciato e il file viene eliminato quando le uscite app.

Quindi, prima di aggiornare l'app.exe, si controlla ci sono eventuali file bloccati nella posizione condivisa, se ci sono file bloccati allora l'app.exe è in uso.

Il programma custode potrebbe essere un'applicazione finestra di meno, il seguente console app fa più o meno quello che deve fare

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

Il programma di aggiornamento cerca quindi per tutti "AppLock_ *" file, e tenta di aprirli con un blocco di scrittura, se non è possibile ottenere un blocco di scrittura su uno di essi, l'exe è in uso.

Spero che questo aiuti.

Questo è quello che ho finito per fare. La scansione della rete non ha funzionato su una rete peer-to-peer. Essa non ha risolto gli altri computer a tutti.

In ogni caso, qui è:

  

Private Sub CheckFileIfFileIsInUse (ByVal thefilename As String)
        Prova
            'Sul sistema operativo Vista è possibile rinominare un file che è in uso
            'La 'in uso' del file originale segue il nuovo nome del file

      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

Spero che questo aiuti la prossima persona.

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top