WinForm关于更新程序的设计思路

   开发WINDOWS应用程序一般都会有一个自动更新的功能,这就需要提供一个单独的更新程序来更新主程序,那么主程序怎么检测是否有更新,以及更新程序怎么去更新主程序呢?下面将分开研究分析。

    用VS发布向导发布的都是安装程序,每次更细都是将整个安装程序下载下来重新安装,有时候安装程序过大而更新又比较平凡(比如我们ERP系统中经常有模块需要升级),为了升级一个单独的模块而升级整个应用程序,这将严重影响用户体验。于是我们采用下载远程模块DLL的方式,客户端用XML文件来保存版本信息,服务器的版本信息保存在数据库中。用户每次运行客户端主程序时,就去检测客户端的版本和服务器端的版本是否一致,不一致的话,就要启动更新程序进行模块更新。这里解释一下为什么要用更新程序去更新主程序,因为我们首先运行的是主程序,主程序在运行过程中是不能更新自己的,因为主程序文件正在使用,不能被远程下载下来的文件覆盖,所以不能在主程序中写更新代码逻辑来更新自己。那怎么解决这个问题呢,这里有一个小技巧,我们在主程序路口点这样处理一下:

using System;  
using System.Collections.Generic;  
using System.Windows.Forms;  
  
  
using MainForm;//主程序窗体所在的DLL  
using System.Diagnostics;  
  
namespace WindowsApplication1  
{  
    static class Program  
    {  
        /// <summary>  
        /// 应用程序的主入口点。  
        /// </summary>  
        [STAThread]  
        static void Main(string[] args)//注意我入口点加了参数,正常创建应用程序时这里是Main()不带参数的  
        {  
             //检测主程序是否是由更新程序启动的  
            if (args.Length > 0 && args[0] == "Updated")  
            {  
//如果是,则运行主程序  
                Application.EnableVisualStyles();  
                Application.SetCompatibleTextRenderingDefault(false);  
      
  
                Application.Run(new XtraForm3());//XtraForm3是主程序窗体  
  
            }  
            else  
            {  
//如果不是,则先运行更新程序检查是否需要更新  
                Process process = new Process();  
                process.StartInfo.FileName = Application.StartupPath + "//YeXin2.0Update.exe";//更新程序所在位置  
                process.Start();//启动更新程序  
                Application.Exit();//关闭主程序  
            }  
              
        }  
    }  
}  

,我们看到,如果不是由更新程序启动的主程序(更新程序如何启动主程序下面介绍),则会启动更新程序,然后关闭自己,让更新程序来更新主程序或者运行主程序。这样主程序就不在运行中,可以下载服务器的主程序DLL来覆盖本地的主程序DLL实现更新主程序的目的。

更新程序的逻辑网上应该有很多,我简单阐述下我的逻辑,版本文件有一个总版本号,然后才是各个模块的自己的版本号。如果总版本号一致,则说明当前是最新程序,不去检查各个模块的版本号,反之,才会去检查各个模块的版本号判断是否需要更新模块。

更新成功后,我们需要同步本地文件的版本信息已经模块DLL并启动主程序。更新成功后我们可以这样写:

CopyFilesDirs(basesavepath, Application.StartupPath);//将下载下来的文件覆盖本地的文件  
  
       Directory.Delete(basesavepath, true);//删除本地临时文件夹  
  
       UpdateVersionFile();//更新本地版本文件信息  
  
       if (MessageBox.Show("更新成功!启动ERP程序吗?""更新提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)  
       {  
  
           if (File.Exists(Application.StartupPath + "//YeXinERP2WinForm.exe"))  
           {  
  
               Process process new Process();  
               process.StartInfo.FileName = Application.StartupPath + "//YeXinERP2WinForm.exe";  
               process.StartInfo.Arguments "Updated";//传递启动参数,这里是重点,主程序入口点需要判断这个参数来判断是否是由更新程序启动的  
               process.Start();  
  
  
           }  
           else  
           {  
               MessageBox.Show("没有找到ERP运行程序!");  
           }  
       }  

这里我是将服务器上下载下来的需要更新的文件保存在一个临时文件夹下面,而不是边下载边覆盖的形式,等全部下载完之后再覆盖本地文件,删除临时文件夹。为什么这样处理呢?因为有时候在下载过程中可能会终止下载(用户点取消下载按钮终止或者非正常终止比如直接KILL更新程序的进程等等),如果采用下载直接写本地文件的方式的话,可能会把本地文件破坏(一个1M的DLL文件,下载到一半的时候中断更新程序,此DLL文件就被破坏了)。

  

一般情况下更新程序做好之后都不会有什么改动,所以不需要更新自己,那么我非要更新自己,该怎么解决呢?那只能把更新程序做成安装程序了。用更新程序下载更新安装程序,下载完后关闭更新程序,运行更新安装程序更新自己。

  

以上是从网上找来的思路,它是启动主程序,然后再启动更新程序,再启动主程序进入程序。既然这样,那么我想,我也可以:直接每次启动更新程序进入主程序,这样做,可以把主程序和更新程序完全分开,以达到更新程序的直接复用。

在更新程序中:

1.可以插入计时器来查看数据库是否可以连接上,以实现可以连上数据库时,自动连上。

2.更新程序。更新完成,启动主程序。

出处:https://blog.csdn.net/spw55381155/article/details/79894055

原文地址:https://www.cnblogs.com/mq0036/p/10585996.html