Pergunta

Eu tenho um programa de atualização que é completamente independente do meu aplicativo principal. Eu executar o Update.exe para atualizar o app.exe. Para verificar se o arquivo está em uso, eu movê-lo para outro arquivo e pegar um erro se ele estiver em uso. Se nenhum problema occurr eu renomeá-lo de volta. Pelo menos isso era o meu plano ...

Main programa: app.exe
programa Update: update.exe

Este programa é utilizado pela rede sem quaisquer serviços em execução. Assim, os usuários é literalmente correr o exe através da rede no mudando máquina.

Eu preciso atualizar o app.exe quando o update.exe foi executado. Para verificar para ver se o app.exe ainda estava em uso Eu estava encerrando o seguinte em um try / catch para ver se ele falhou:

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

O engraçado é que, mesmo se o app.exe está em execução, o movimento pode renomeá-lo para o app.exe.tst sem qualquer erro. Posso até continuar na aplicação sem erros.

Eu pensei que estava fora da minha mente, então eu tinha um outro olhar programador para isso e ele verificou que eu disse acima.

Então, nós tentamos isso envolto em um try catch:

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

Eu coloquei o fileshare como nenhum que, pelo menos eu pensei que seria, mostram que havia alguém no arquivo.

Ele ainda continuou sem qualquer erro.

Alguém sabe por que eu posso renomear um arquivo em uso? Além disso, há uma maneira melhor de fazer isso do que o que eu estou fazendo agora?

Obrigado! Eroc

Foi útil?

Solução

Você pode fazer o seguinte para verificar se o aplicativo tem outras instâncias em execução:

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

Qual é a forma mais adequada de verificar se o aplicativo está sendo executado.

Tenha um olhar em File.Move documentação MSDN. Ele detalha o que exceções são lançadas. Você tem permissão para mudar o nome de um exe, mesmo se ele estiver em uso no Vista.

Outras dicas

O mesmo código usando "usando":)

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

O que você poderia fazer é substituir o aplicativo de destino com um exe zelador.

Esta zelador, em seguida, gera a aplicação de destino, mas também cria um arquivo bloqueado em um local compartilhado. A trava é liberada e o arquivo é excluído quando sai do aplicativo.

Então, antes de atualizar o app.exe, você verificar existem arquivos bloqueados no local compartilhado, se houver arquivos bloqueados em seguida, o app.exe está em uso.

O programa zelador poderia ser um aplicativo de janela menos, a seguinte aplicação de console faz muito bem o que ele precisa fazer

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

O atualizador em seguida, olha para todos "AppLock_ *" arquivos e tentativas de abri-los com um bloqueio de gravação, se não for possível obter um bloqueio de gravação em um deles, o exe está em uso.

Espero que isso ajude.

Isto é o que eu acabei fazendo. A digitalização em rede não funciona em uma rede peer-to-peer. Não resolver os outros computadores em tudo.

De qualquer forma, aqui está:

Private Sub CheckFileIfFileIsInUse (ByVal thefilename As String)
tente
'Sobre o sistema operacional Vista, você pode renomear um arquivo que está em uso
'The 'em uso' do arquivo original segue o novo nome de arquivo

      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 isso ajuda a próxima pessoa.

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top