0

以下代码应该替换可执行文件并重新启动应用程序,这应该可以工作,因为内容应该被替换但不在当前运行的实例中:

Dim tmppath As String = System.IO.Path.GetTempFileName

Private Sub YesBtn_Click(sender As Object, e As EventArgs) Handles YesBtn.Click
    Dim client As New WebClient()
    AddHandler client.DownloadProgressChanged, AddressOf client_ProgressChanged
    AddHandler client.DownloadFileCompleted, AddressOf client_DownloadFileCompleted
    client.DownloadFileAsync(New Uri("https://github.com/Yttrium-tYcLief/Scrotter/raw/master/latest/scrotter.exe"), tmppath)
End Sub

Public Sub client_DownloadFileCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs)
    File.Replace(tmppath, Application.ExecutablePath, Nothing)
    Application.Restart()
End Sub

根据MSDN

如果您不想创建被替换文件的备份,请将Nothing传递给 destinationBackupFileName 参数。

然而,真正发生的是它确实创建了一个备份(如果 .exe 是scrotter.exe,那么新的备份是scrotter.exe~RF729c1fe9.TMP)。此外,还会在根目录中创建一个名为“False”的新空文件夹。

我想要的只是用我的文件替换正在运行的可执行文件,并且没有任何备份或额外的文件夹。有任何想法吗?

4

2 回答 2

1

很难用发布的代码来解释这一点,这听起来像是某种第 3 方实用程序介入并避免了您的代码存在的问题。当您为备份文件名传递 Nothing 时,它将永远不会起作用。如果要替换也加载到内存中的可执行文件,则需要它。CLR 为程序集创建一个内存映射文件对象,以便 Windows 可以根据需要将程序集中的数据分页到 RAM 中。最大的优势是这不会占用页面文件中的任何空间。该 MMF 还对文件进行了硬锁定,因此没有人可以更改文件内容。那将是灾难性的。

这是对文件数据的锁定,而不是文件的目录条目。所以重命名文件仍然有效。当您提供非空备份文件名时,File.Replace() 会执行此操作,它会重命名程序集,因此您仍然可以创建具有相同名称的文件而不会遇到锁定问题。您可以在之后删除备份副本,假设您的程序在启动备份时仍然有足够的权限实际删除文件。如今,这在 UAC 中是不寻常的。或者只是不打扰,磁盘空间很便宜,并且有一个备份副本来处理事故是你可以称之为功能的东西。

所以继续并正确使用 File.Replace() ,使用第三个参数。在调用 Replace() 之前不要忘记删除该备份文件。

于 2013-05-12T13:31:00.517 回答
0

我认为只要您的进程运行,.exe 就会被锁定 - 哪个实例运行无关紧要。为避免这种情况,我会将更新程序放在单独的 .exe 中,并在更新时关闭您的主应用程序。

于 2013-05-12T09:00:31.970 回答