在日常工作中,软件需要实现更新!在linux环境下,只需要检查版本号,拿到最新下载地址,下载解压替换掉执行文件然后重启即可。
但是在windows下,在程序未停止前是无法实现可执行文件替换的,所以在windows环境下,以多提供一个upgrade.exe的更新程序来实现。
具体实现方案:
1.检查版本,下载更新包;
2.执行upgrade.exe,并退出程序,解除程序暂用
3.upgrade程序实现更新包的解压,替换主程序
4.upgrade执行程序包.
这样就达到了程序的更新操作.
具体代码实现:
1.检查版本,并下载
func (s *ServerImpl) winUpgrade(e echo.Context) error { spVersion, err := servers.NewReportService().CheckVersion(1, 0) if err != nil { return errors.New("网络错误") } // 比较版本 if utils.CompareVersion(spVersion.Code, config.Version) != 1 { return e.JSON(http.StatusOK, "已经是最新版") } fmt.Println("Download Started") if spVersion.Down == "" { return errors.New("网络错误") } resp, err := http.Get(spVersion.Down) if err != nil { return errors.New("更新失败") } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return errors.New("更新失败") } // 保存文件 zipReader, err := zip.NewReader(bytes.NewReader(body), int64(len(body))) if err != nil { return errors.New("更新失败") } // 解压 if err = utils.DeCompress(zipReader.File, "./new_version"); err != nil { return errors.New("更新失败") } fmt.Println("Download Finished") go func() { // 唤起upgrade.exe start是非阻塞 /B是隐藏窗口 cmd := exec.Command("cmd.exe", "/C", "start", "/B", "upgrade.exe") if err = cmd.Start(); err != nil { fmt.Println(err) } fmt.Println("exit") os.Exit(0) }() return e.JSON(http.StatusOK, "更新成功") }
upgrade 程序替换并唤起主程序
// cmd的start执行不会等待命令完成,Run会阻塞等待命令完成
func main() {
fmt.Println("upgrade....")
fmt.Println("rename:")
os.Rename("cms.exe", fmt.Sprintf("%s-%s.exe", "cms", time.Now().Format("20060102150405")))
// 重命名cms.exe
os.Rename("./new_version/cms.exe", "./new_version/cms_new.exe")
gfile.CopyDir("./new_version/html", "./html")
if err := gfile.Copy("./new_version/cms_new.exe", "./cms.exe"); err != nil {
fmt.Println("copy err", err)
time.Sleep(10 * time.Second)
os.Exit(0)
}
gfile.Remove("./new_version")
//os.Rename("cms_new.exe", "cms.exe")
fmt.Println("starting.......")
cmd := exec.Command("cmd.exe", "/C", "start", "cms.exe")
if err := cmd.Start(); err != nil {
fmt.Println(err)
}
time.Sleep(5 * time.Second)
fmt.Println("upgrade exit")
os.Exit(0)
}
这样就达到了,程序更新的效果
2023.09.06
最近在优化windows的软件的更新,找到了更好的方法而不依赖第三方程序;即在windows下可以通过重命名可执行文件,来解决windows可执行文件被占用的问题!
首先把正在运行的可执行文件a.exe改成c.exe,然后把更新的可执行文件b.exe重命名为a.exe,最后重启程序。这样就达到了软件的自我更新。
直接上demo
func main() {
err := os.Rename("./cms-test.exe", "./cms-test-temp.exe")
if err != nil {
fmt.Print(err)
return
}
time.Sleep(5 * time.Second)
os.Rename("./cms.exe", "./cms-test.exe")
time.Sleep(2 * time.Second)
os.Remove("./cms-test-temp.exe")
time.Sleep(5 * time.Second)
// 到程序安装路径下去执行启动命令(预防相对路径方式启动)
daemon := "timeout /T 3 & E:\\cms\\cms-test.exe 2>&1 &"
_ = exec.Command("cmd.exe", "/C", daemon).Start()
}