Вопрос

У меня есть программа обновления, полностью независимая от моего основного приложения.Я запускаю update.exe, чтобы обновить app.exe.Чтобы проверить, используется ли файл, я перемещаю его в другой файл и обнаруживаю ошибку, если он используется.Если проблем не возникает, я переименовываю его обратно.По крайней мере, это был мой план...

Основная программа:приложение.exe
Обновление программы:обновление.exe

Эта программа используется по сети без запуска каких-либо служб.Таким образом, пользователи буквально запускают exe-файл по сети на своем компьютере.

Мне нужно обновить app.exe после запуска update.exe.Чтобы проверить, используется ли еще app.exe, я включил следующее в try/catch, чтобы проверить, не удалось ли это:

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

Самое смешное, что даже если app.exe запущен, этот ход позволяет без каких-либо ошибок переименовать его в app.exe.tst.Я даже могу продолжить работу с приложением без каких-либо ошибок.

Я думал, что сошел с ума, поэтому попросил другого программиста посмотреть на это, и он подтвердил то, что я сказал выше.

Итак, мы попробовали это, завернув в try catch:

Тусклый файл чтения как новый FileStream (upddir & «\app.exe», FileMode.Open, FileAccess.Read, FileShare.None)
readfile.Dispose()

Я указал общий доступ к файлу как «Нет», чтобы, по крайней мере, я так думал, показать, что в файле кто-то есть.

Оно по-прежнему продолжалось без каких-либо ошибок.

Кто-нибудь знает, почему я могу переименовать используемый файл?Кроме того, есть ли лучший способ сделать это, чем то, что я делаю сейчас?

Спасибо!Эрок

Это было полезно?

Решение

Вы можете сделать следующее, чтобы проверить, есть ли у приложения другие запущенные экземпляры:

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

Это более подходящий способ проверить, работает ли приложение.

Посмотри на Файл.Переместить Документация MSDN.В нем подробно описано, какие исключения выдаются.Вам разрешено переименовывать exe-файл, даже если он используется в Vista.

Другие советы

Тот же код с использованием «использования» :)

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

Что вы можете сделать, так это заменить целевое приложение на исполняемый файл-смотритель.

Затем этот смотритель порождает целевое приложение, а также создает заблокированный файл в общем расположении.Блокировка снимается, и файл удаляется при выходе из приложения.

Затем, прежде чем обновлять app.exe, вы проверяете, есть ли заблокированные файлы в общей папке. Если есть заблокированные файлы, значит, используется app.exe.

Программа-сторож может быть приложением без окон, следующее консольное приложение делает почти то, что ему нужно.

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

Затем программа обновления ищет все файлы «AppLock_*» и пытается открыть их с блокировкой записи. Если не удается получить блокировку записи для одного из них, это означает, что exe-файл используется.

Надеюсь это поможет.

Вот что я в итоге сделал.Сетевое сканирование не работало в одноранговой сети.Другие компьютеры вообще не разрешились.

Во всяком случае, вот оно:

Частный дополнительный CheckFileIfFileIsInUse (по значению имени файла как строка)
Пытаться
' в ОС Vista вы можете переименовать используемый файл
' 'используется' исходного файла следует за новым именем файла

      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 />

Конец субтитра

Надеюсь, это поможет следующему человеку.

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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top