window平台C#实现软件更新功能

 一 实现程序更新思路

    程序实现自我升级,一般有两种方式:

1. 独立的更新程序

开发一个独立的更新程序如Update.exe,用于检查主程序是否有新版本,并下载和安装新版本。

实现步骤:

  1. 主程序启动完后,调用一下更新程序。
  2. 更新程序检查版本不需要更新就退出否则执行更新。
  3. 更新程序检查主程序的版本号。
  4. 如果主程序的版本号低于服务器上的版本号,则下载新版本。
  5. 下载完成后,更新程序将新版本安装到主程序的目录中(一般要备份旧版的)。
  6. 更新程序重启主程序。

优点:

  • 更新过程对用户透明,用户无需手动操作。
  • 可以实现增量更新,只下载更新的文件,节省流量。

缺点:

  • 更新程序需要访问服务器,如果服务器不可访问,则无法更新。

2. 主程序自带更新功能

 将更新功能集成到主程序中,无需开发额外的更新程序。

实现步骤如下:

  1. 主程序启动时,向服务器发送请求,检查是否有新版本。
  2. 如果有新版本,则服务器返回新版本的版本号和下载地址。
  3. 主程序下载新版本。
  4. 下载完成后,主程序将新版本安装到自己的目录中。
  5. 主程序重启自身。

优点:

  • 开发简单,在更新过程中无需考虑与主程序通讯。

缺点:

  • 每次更新都需要下载整个程序,比较耗流量,在更新后不能很好实现自我重启,需要用脚本或者其它方式。

二  程序更新代码(独立的更新程序

 1 主程序增加调用更新程序代码:

  public void CheckForUpdates()
        {
            // 检查是否存在更新程序
            if (File.Exists("Update.exe"))
            {

                // 启动更新程序
                try
                {
                    Process.Start("Update.exe");
                }
                catch (Exception e)
                {
                    
                }
              
            }
  }

2 update.exe完整代码:

        //这部分用于隐藏窗体或控制台,一般静默更新,重启才提示。

        [DllImport("kernel32.dll")]
        static extern IntPtr GetConsoleWindow();

        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        const int SW_HIDE = 0;
        String processName = "xxx平台";
        String mainFilePath = "xxx平台.exe";
        String infaceVersion = "";
        String updateUrl = "http://192.168.22.100:1888/pc/getVersionInfo";
        String downloadUrlExe = "http://192.168.22.144:8904/common/downloadAppFile/2666c50a-6e1c-4a8a-b8f6-c1a5002d4ca0.exe";
        String downloadFileName = "test.exe";
        public Form1()
        {

            InitializeComponent();

            // 获取控制台窗口句柄
            IntPtr hWnd = GetConsoleWindow();
            // 隐藏控制台窗口
            ShowWindow(hWnd, SW_HIDE);

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            
            Update();
        }




        //更新程序
        public void Update()
        {
            // 获取主程序的版本号
            String version = GetVersion(mainFilePath);

            // 检查是否有新版本
            String newVersion = GetVersionFromWeb();

            if (newVersion != null)
            {
               
                // 如果有新版本,则下载新版本
                if (CompareVersion(newVersion, version) == 1)
                {
                    Log("本地版本:"+version);

                    Log("符合更新条件,开始更新…");

                    Log("开始下载…");
                    if (DownloadNewVersion())
                    {


                        // 安装新版本
                        Log("开始更新程序…");
                        InstallNewVersion();


                        Log("启动主程序…");
                        // 重启主程序
                        Process.Start(mainFilePath);
                        Log("启动主程序ok");

                    }
                    else
                    {
                        Log("因下载环节问题终止更新操作!");
                    }

          



                   

                }
                else
                {
                    Log("没有的新条件,退出");
                }


            }
            else
            {
                Log("获取服务器版本失败!");
            }

            Log("更新程序退出.");

            Environment.Exit(0);

        }

        /// <summary>
        /// 下载新版本并验证版本号
        /// </summary>
        /// <returns></returns>
        private Boolean DownloadNewVersion()
        {
            WebClient wcClient = new WebClient();


            // 下载文件并保存到指定位置
            WebClient client = new WebClient();
            Log("获取下载url: "+ downloadUrlExe);

            byte[] data = client.DownloadData(downloadUrlExe);

            Log("下载文件大小[" + data.Length/1024 + " kb]");

            String tempPath = "./" + downloadFileName;
            // 将字节数组保存到文件
            File.WriteAllBytes(tempPath, data);
            Log("保存位置 " + tempPath);


            //验证版本 是否与接口一致
            String version = GetVersion(tempPath);
            bool vaildVersion = version.Equals(infaceVersion);
            Log("验证已下载文件版本("+version+")与 接口版本("+infaceVersion+"): " + vaildVersion);
           
            return vaildVersion;

        }


        /// <summary>
        /// 安装
        /// </summary>
        private void InstallNewVersion()
        {

            Log("开始关闭主程序…");
            Process[] ppp= Process.GetProcessesByName(processName);
            if (ppp.Length > 0)
            {
                MessageBox.Show("正在执行升级,重启远程鉴定平台。");
                try
                {
                    for (int i = 0; i < ppp.Length; i++)
                    {
                        Log("结束进程:" + ppp[i].ProcessName);
                        ppp[i].Kill();

                    }
                }
                catch(Exception ex)
                {
                    Log("结束进程:" +ex.Message);
                }

               
            }

            Log("备份主程序…");
            if (!Directory.Exists("./bak"))
            {
                Directory.CreateDirectory("./bak");
            }

            DateTime currentDateAndTime = DateTime.Now;
            String time= currentDateAndTime.ToString("yyyyMMddHHmmss");
            String bakPath = "./bak/" + mainFilePath + "." + time;
            File.Copy(mainFilePath,bakPath,true);
            Log("备份主程序完成。");

            int waitTimeMilliseconds = 1000; // 5秒
            Thread.Sleep(waitTimeMilliseconds);

            File.Delete(mainFilePath);
            Log("删除旧版程序OK。 ");

            File.Copy(downloadFileName,mainFilePath);
            Log("更新文件OK。 ");

            File.Delete(downloadFileName);
            Log("删除下载文件OK。 ");


        }


        private String GetVersionFromWeb()
        {
            Log("准备获取服务器版本号…");

            String json =request(updateUrl);

            //{"msg":"操作成功","code":200,"data":{"id":589,"versionCode":3,"versionName":"1.0.0.1","updateContent":"test","fileName":"xxx平台.exe","saveName":"2666c50a-6e1c-4a8a-b8f6-c1a5002d4ca0.exe","fileSuffix":".exe","fileSize":"107KB","url":"http://192.168.22.144:8904/common/downloadAppFile/2666c50a-6e1c-4a8a-b8f6-c1a5002d4ca0.exe","type":2,"uploadTime":"2024-03-26 10:17:29"}}
  
            JsonElement element = JsonDocument.Parse(json).RootElement;

            infaceVersion = element.GetProperty("data").GetProperty("versionName").GetString();
            Log("获取服务器版本号:" + infaceVersion);

            downloadUrlExe = element.GetProperty("data").GetProperty("url").GetString();
            Log("获取服务器下载URL:" + downloadUrlExe);

            downloadFileName = element.GetProperty("data").GetProperty("saveName").GetString();
            Log("获取服务器下载文件名称:" + downloadFileName);

            return infaceVersion;
        }


        /// <summary>
        /// 日记记录
        /// </summary>
        /// <param name="v"></param>
        private void Log(string v)
        {
            //DateTime currentDateAndTime = DateTime.Now;
            //richTextBox1.AppendText(currentDateAndTime.ToString() +" - "+ v+"\n");

            String filePath = "./update.log";
            try
            {
                using (StreamWriter writer = new StreamWriter(filePath, true))
                {
                    string logEntry = $"{DateTime.Now} - {v}";
                    writer.WriteLine(logEntry);
                }
              
            }
            catch (Exception ex)
            {
                // 记录异常信息
                Console.WriteLine("日志记录失败:" + ex.Message);
            }

        }

        /// <summary>
        /// http请求
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string request(string url)
        {
            using (WebClient client = new WebClient())
            {
                return client.DownloadString(url);
            }
        }

        /// <summary>
        /// 获取文件版本号
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private String GetVersion(string path)
        {
            richTextBox1.AppendText("准备获取本地版本号……:" + path+"\n");

            // 获取文件版本信息
            FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(path);

            // 获取文件版本号
            string fileVersion = fileVersionInfo.FileVersion;

            richTextBox1.AppendText("获取本地版本号:" + fileVersion + "\n");
            return fileVersion;
        }

        /// <summary>
        /// 比较软件的版本号
        /// </summary>
        /// <param name="version1"></param>
        /// <param name="version2"></param>
        /// <returns></returns>
        public static int CompareVersion(string version1, string version2)
        {
            string[] parts1 = version1.Split('.');
            string[] parts2 = version2.Split('.');

            for (int i = 0; i < parts1.Length && i < parts2.Length; i++)
            {
                int v1 = int.Parse(parts1[i]);
                int v2 = int.Parse(parts2[i]);

                if (v1 > v2)
                {
                    return 1;
                }
                else if (v1 < v2)
                {
                    return -1;
                }
            }

            return 0;
        }

执行后的更新日记 

 

相关推荐

  1. C#深入.NET软件系统分层开发

    2024-03-26 18:50:02       29 阅读
  2. windowsQt5连接wifi

    2024-03-26 18:50:02       18 阅读
  3. c++跨ui

    2024-03-26 18:50:02       36 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-26 18:50:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-26 18:50:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-26 18:50:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-26 18:50:02       20 阅读

热门阅读

  1. unity 2d范围检测:怪物检测范围

    2024-03-26 18:50:02       17 阅读
  2. 论低代码如何适配小程序开发

    2024-03-26 18:50:02       18 阅读
  3. npm安装yarn和pnpm

    2024-03-26 18:50:02       20 阅读
  4. 前端理论总结(html5)——meta标签作用/SEO优化

    2024-03-26 18:50:02       18 阅读
  5. 算法-排序,查找

    2024-03-26 18:50:02       18 阅读
  6. go语言数组的增删改查

    2024-03-26 18:50:02       20 阅读
  7. Tomcat 启动闪退问题解决方法

    2024-03-26 18:50:02       16 阅读