golang 应用在windows环境实现自我更新

在日常工作中,软件需要实现更新!在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()
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值