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

 

这样就达到了,程序更新的效果