2

我有一个完全独立于我的主应用程序的更新程序。我运行 update.exe 来更新 app.exe。为了检查文件是否在使用中,我将它移动到另一个文件中,如果它正在使用中就会发现一个错误。如果没有问题发生,我将其重命名。至少那是我的计划……

主程序:app.exe
更新程序:update.exe

该程序在网络上使用,没有运行任何服务。因此,用户实际上是在他们的机器上通过网络运行 exe。

当 update.exe 运行时,我需要更新 app.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在运行,move也可以将其重命名为app.exe.tst而不会出现任何错误。我什至可以继续在应用程序中没有任何错误。

我以为我疯了,所以我让另一个程序员看看这个,他验证了我上面所说的。

所以,我们在 try catch 中尝试了这个:

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

我将文件共享设置为无,至少我认为它会表明文件中有人。

它仍然继续,没有任何错误。

有人知道为什么我可以重命名正在使用的文件吗?另外,有没有比我现在做的更好的方法来做到这一点?

谢谢!爱罗克

4

5 回答 5

7

使用“使用”的相同代码:)

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
于 2011-03-21T16:00:14.350 回答
1

您可以执行以下操作来检查应用程序是否有其他实例正在运行:

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

这是检查应用程序是否正在运行的更合适的方法。

查看File.Move MSDN 文档。它详细说明了引发了哪些异常。即使在 Vista 中使用,您也可以重命名 exe。

于 2009-07-03T12:01:06.333 回答
1

您可以做的是用看守 exe 替换目标应用程序。

然后这个看守人会生成目标应用程序,但也会在共享位置创建一个锁定文件。当应用程序退出时,锁定被释放并且文件被删除。

然后,在更新 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 正在使用中。

希望这可以帮助。

于 2009-07-03T12:52:47.427 回答
0

这就是我最终做的。网络扫描在对等网络上不起作用。它根本没有解决其他计算机。

无论如何,这里是:

Private Sub CheckFileIfFileIsInUse(ByVal thefilename As String)
Try
' 在 Vista 操作系统上,您可以重命名正在使用
的文件 ' 原始文件的 'in use' 遵循新文件名

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

结束子

希望这可以帮助下一个人。

于 2009-07-06T18:29:28.287 回答
0
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
于 2009-11-20T03:58:43.723 回答