VB.Net 3.5 Comprobar si el archivo está en uso
Pregunta
Tengo un programa de actualización que es completamente independiente de mi aplicación principal. Puedo ejecutar el Update.exe para actualizar el app.exe. Para comprobar para ver si el archivo está en uso, lo muevo a otro archivo y coger un error si está en uso. Si no hay problemas occurr puedo cambiar el nombre de nuevo. Al menos esa era mi plan ...
programa principal: app.exe
Programa de actualización: update.exe
Este programa es utilizado por la red sin ningún tipo de servicios que se ejecutan. Así, los usuarios es, literalmente, corriendo el exe través de la red a emabrgo máquina.
Es necesario que actualice la app.exe cuando el update.exe se ha ejecutado. Para comprobar para ver si el app.exe todavía estaba en uso estaba envolviendo el siguiente en un try / catch para ver si fallaba:
IO.File.Move (upddir & "\ app.exe", upddir & "\ app.exe.tst")
IO.File.Move (upddir & "\ app.exe.tst", upddir & "\ app.exe")
Lo curioso es que, incluso si el app.exe está funcionando, el movimiento puede cambiar el nombre a la app.exe.tst sin ningún error. Incluso puedo continuar en la aplicación sin ningún error.
pensé que estaba fuera de mi mente, así que tenía otra mirada programador en esto y verificado lo que he dicho anteriormente.
Por lo tanto, hemos intentado esto envuelto en un intento de captura:
readfile Dim como nuevo FileStream (upddir & "\ app.exe", FileMode.Open, FileAccess.Read, FileShare.NONE)
readfile.Dispose ()
pongo el uso compartido de archivos, ya que ninguno de que, al menos, pensé que sería, muestran que había alguien en el archivo.
Todavía continuó sin ningún error.
Alguien sabe qué puedo cambiar el nombre de un archivo en uso? Además, hay una mejor manera de hacer esto que lo que estoy haciendo ahora?
Gracias! Eroc
Solución
Se puede hacer lo siguiente para comprobar si la aplicación tiene otras instancias en ejecución:
Process.GetProcessesByName("app.exe", "Machine1").Length > 0
¿Qué es una forma más adecuada de comprobar si la aplicación se está ejecutando.
Tener un vistazo a File.Move documentación de MSDN. En él se detalla lo que se producen excepciones. Se le permite cambiar el nombre de un archivo EXE, incluso si está en uso en Vista.
Otros consejos
El mismo código utilizando el "uso":)
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
Lo que podría hacer es sustituir la aplicación de destino con un exe cuidador.
Este cuidador continuación, genera la aplicación de destino, sino que también crea un archivo bloqueado en una ubicación compartida. El bloqueo se libera y se elimina el archivo cuando se cierra la aplicación.
A continuación, antes de actualizar el app.exe, devolver a la salida ¿Hay algún archivo bloqueado en la ubicación compartida, si hay archivos bloqueados, la app.exe está en uso.
El programa cuidador podría ser una aplicación sin ventanas, la siguiente aplicación de consola hace bastante más de lo que tiene que hacer
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");
}
}
El proceso de actualización a continuación, busca todos los "AppLock_ *" archivos, e intenta abrirlos con un bloqueo de escritura, si no puede obtener un bloqueo de escritura en uno de ellos, el exe está en uso.
Espero que esto ayude.
Esto es lo que terminé haciendo. El análisis de la red no funcionaba en una red peer-to-peer. No resolver las otras computadoras en absoluto.
De todos modos, aquí está:
Private Sub CheckFileIfFileIsInUse (ByVal thefilename como secuencia)
Trate
'En el sistema operativo Vista se puede cambiar el nombre de un archivo que está en uso
"La 'en uso' del archivo original sigue el nuevo nombre de archivo
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
Espero que esto ayuda a la siguiente 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