以下代码应该替换可执行文件并重新启动应用程序,这应该可以工作,因为内容应该被替换,但不能在当前运行的实例中替换:
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
,那么新备份是{{1} })。此外,在根目录中创建一个名为“False”的新空文件夹。
我想要的只是用我的文件替换正在运行的可执行文件,而不是任何备份或额外的文件夹。有什么想法吗?
答案 0 :(得分:1)
很难用发布的代码来解释这一点,这有点像某种第三方实用程序踩到并避免代码所带来的问题。当您为备份文件名传递Nothing时,它将永远不会工作。如果要替换也加载到内存中的可执行文件,则必需。 CLR为程序集创建了一个内存映射文件对象,因此Windows可以根据需要将数据从程序集分页到RAM中。具有很大的优势,这不会占用页面文件中的任何空间。该MMF还对文件进行了硬锁定,因此没有人可以更改文件内容。那将是灾难性的。
这是对文件数据的锁定,而不是文件的目录条目。所以重命名文件仍然有效。这是File.Replace()在提供非空备份文件名时所执行的操作,它重命名程序集,因此您仍然可以创建具有相同名称的文件,而不会遇到锁定问题。您可以删除备份副本,假设您的程序在启动备份时仍具有足够的权限来实际删除该文件。这对于UAC来说这是不寻常的。或者只是不打扰,磁盘空间很便宜,并且有一个备份副本来处理事故是你可以称之为功能的东西。
因此,请正确使用File.Replace(),使用第3个参数。在调用Replace()之前,不要忘记删除该备份文件。
答案 1 :(得分:0)
我认为只要您的进程运行,.exe就会被锁定 - 哪个实例运行无关紧要。 为避免这种情况,我会将更新程序放在单独的.exe中,并在更新时关闭主应用程序。