window平台C#实现软件升级功能(控制台)

news2025/1/18 4:43:53

 window平台C#实现软件升级功能

       之前用window窗体实现过一个升级功能,后来发现多个项目都需要升级功能,现改成可接收参数实现一种通用的exe.改用控制台方式实现这个升级功能,这样不仅实现了接收参数,升级程序体积也比原来的窗体形式更小。

一  Window窗体升级实现:

window平台C#实现软件升级功能(Window窗体应用)_开发电脑软件自动更新怎么实现-CSDN博客

 

二  控制台升级实现:

  1 关于升级细路,这里不再详细写,可参考上面Window窗体升级实现。

  2 完整C#控制台升级程序代码如下:

using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Runtime.InteropServices;
using System.Text.Json;
using System.Threading;

namespace ConsoleAppUpdate
{
    class Program
    {
        static String processName = "xxx应用";
        static String mainFilePath = "xxx应用.exe";
        static String infaceVersion = "";

       
        static String updateUrl = "https://xxx.xxx.xxx.xxx/pc/getLastApp";
        static String downloadUrlExe = "http://xxx.xxx.xxx.xx:89/common/downloadAppFile/2666c50a-6e1c-4a8a-b8f6-c1a5002d4ca0.exe";
        static String downloadFileName = "test.exe";

        // 导入 Windows API 函数
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

        // 用visual studio 编译时 要配置
        static void Main(string[] args)
        {
            // 参数1 升级接口 url
            // 参数2 进程名称 用于关闭进程
            // 参数3 主文件名称 (不用指定目录,要求把升级文件放在主文件同一目录即可)
            if (args != null && args.Length > 1)
            {
                updateUrl = args[0];
                Log("rev update url = " + updateUrl);
            }
            else
            {
                Log("use default update url = " + updateUrl);
            }
            try
            {
                Update();
            }
            catch (Exception ee)
            {
                Log("update program Exception :" + ee.Message);

            }
            finally
            {
                Environment.Exit(0);
            }
        }



        //更新程序
        public static void Update()
        {
            Log("开始检测更新……");
            // 获取主程序的版本号
            String version = GetVersion(mainFilePath);

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

            if (newVersion != null)
            {

                if ("0.0.0.0".Equals(version))
                {
                    Log("原主程序,直接更新.");
                    Log("开始下载…");
                    if (DownloadNewVersion())
                    {


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


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

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


                }
                else
                {
                    // 如果有新版本,则下载新版本
                    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 static 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 static void InstallNewVersion()
        {

            Log("开始关闭主程序…");
            Process[] ppp = Process.GetProcessesByName(processName);
            if (ppp.Length > 0)
            {
                MessageBox(IntPtr.Zero, "正在执行升级,重启远程鉴定平台。", "升级提示", 0);
                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;

            if (File.Exists(mainFilePath))
            {
                File.Copy(mainFilePath, bakPath, true);
                Log("备份主程序完成。");

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

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

            if (downloadFileName.EndsWith(".zip",StringComparison.CurrentCultureIgnoreCase))
            {
                //如果升级包是zip 先解压
                try
                {
                    // 解压zip文件到当前目录
                    ZipFile.ExtractToDirectory(downloadFileName, "./");
                    Console.WriteLine("Zip文件解压成功!");
                    File.Delete(downloadFileName);
                    Log("删除下载文件OK。 ");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("解压zip文件时出错:" + ex.Message);
                }

            }
            else
            {
                File.Copy(downloadFileName, mainFilePath);
                Log("更新主程序完成。");

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

          


        }


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

            String json = request( updateUrl);

            //{"msg":"操作成功","code":200,"data":{"versionName":"1.0.0.1","updateContent":"test","fileSize":"107KB","url":"http://192.168.22.144:8904/common/downloadAppFile/2666c50a-6e1c-4a8a-b8f6-c1a5002d4ca0.exe","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 static void Log(string v)
        {
    
            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 static String GetVersion(string path)
        {
            Log("获取本地版本号……:" + path + "\n");

            if (!File.Exists(path))
            {
                string currentDirectory = Directory.GetCurrentDirectory();
                Console.WriteLine("Current Directory: " + currentDirectory);
                path = currentDirectory + "\\" + path;

                if (!File.Exists(path))
                {
                    Log("检测不到主文件,直接返回原始版本号");
                    return "0.0.0.0";
                }
            }

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

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

            Log("获取本地版本号:" + 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. 打开 Visual Studio 中的项目。
  2. 在解决方案资源管理器中,右键单击项目,然后选择“属性”。
  3. 在属性窗口中,选择“应用程序”选项卡。
  4. 在“输出类型”下拉菜单中选择“Windows 应用程序”。
  5. 保存更改并重新构建项目。

如下图:

代码编译后,发现引用了很多dll,原因是因为升级接口返回的是json数据所以使用了一个json解析用到几个dll,需要复制到需要用到升级功能的项目即可。

实现效果图如下:

 

查看更新日记 

 

测试完美实现更新。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1622783.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java自动生成pojo,springboot自动生成pojo

第一步 pom引入依赖 <dependencies><!-- mybatis-generator --><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.7</version></dependency>&…

开源电商小程序源码+搭建 支持全平台端口+商家自营+多商户入驻 带分销功能 可自用DIY界面

开源电商小程序源码系统为商家提供了一个快速搭建和部署电商平台的解决方案。商家可以利用该系统&#xff0c;在较短的时间内构建出功能齐全、界面美观的电商小程序&#xff0c;无需从零开始编写代码&#xff0c;从而大大节省了开发成本和时间。 分享一个开源电商小程序源码系…

OpenUI在windows下部署使用

OpenUI OpenUI是一个基于Python的AI对话平台&#xff0c;支持接入多种AI模型。 通过聊天的方式来进行UI设计&#xff0c;你可以通过文字来描述你想要的UI界面&#xff0c;OpenUI可以帮你实时进行渲染出效果 安装OpenUI 这里预设你的电脑上已安装git、Python和pip&#xff0…

Nginx 搭建Web服务

题目&#xff1a; 1.web服务器的主机ip&#xff1a;192.168.78.128 2.web服务器的默认访问目录为/var/www/html 默认发布内容为default‘s page 3.站点news.timinglee.org默认发布目录 为/var/www/virtual/timinglee.org/news 默认发布内容为 news.timinglee.org 4.站点login.t…

Power BI 如何解决月份排序错误/乱序问题(自定义顺序/正确排序)

问题描述 在创建图标时&#xff0c;月份标签没有按照正确的顺序排列。 解决方案&#xff1a; Sort by Column 单击选中排序错误的列&#xff08;MMM&#xff09;根据列排序 (sort by Column)选择需要根据哪一列排序。 这里选择的是Month列&#xff0c;这一列有月份的序号1-…

如何通过香港站群服务器提升跨境电商交易效率?

如何通过香港站群服务器提升跨境电商交易效率? 在全球电子商务迅速发展的今天&#xff0c;跨境电商已成为企业拓展国际市场、获取更多商机的重要途径。然而&#xff0c;跨境电商面临的挑战也不容小觑&#xff0c;尤其是在交易效率方面。利用香港站群服务器&#xff0c;不仅可…

做抖音小店如何选品?这几个技巧,精准“锁定”爆品!

哈喽~我是电商月月 做抖音小店最重要的就是选品&#xff0c;这点大家都知道 一个店铺商品选的好&#xff0c;顾客喜欢&#xff0c;质量完好&#xff0c;销量和售后都不用操心&#xff0c;和达人合作时&#xff0c;爆单的机会也就越高 那这种商品是什么样的&#xff0c;新手开…

快速了解-BTP

名词了解 BTP&#xff1a;SAP Business Technology Platform 是一个技术和业务的平台ETWEAVER &#xff08;SAP NW&#xff09;&#xff1a;NetWeaver本质上是SAP一系列技术产品的集成平台PAAS Cloud Foundry&#xff08;云原生&#xff09;&#xff1a;开源云服务平台烟囱式…

通配符/泛域名证书的五大优势

在数字化时代&#xff0c;网络安全成为企业及个人关注的焦点。为了确保在线信息传输的安全性与私密性&#xff0c;SSL/TLS证书成为网站加密通信的重要工具。其中&#xff0c;通配符证书作为一种特殊类型的SSL证书&#xff0c;以其独特的优势在众多证书类型中脱颖而出&#xff0…

Python程序设计教案

文章目录&#xff1a; 一&#xff1a;软件环境安装 第一个软件&#xff1a;pycharm 第二个软件&#xff1a;thonny 第三个软件&#xff1a;IDIE&#xff08;自带的集成开发环境&#xff09; 二&#xff1a;相关 1.规范 2.关键字 3.Ascll码表 三&#xff1a;语法基础…

LeetCode-2007. 从双倍数组中还原原数组【贪心 数组 哈希表 排序】

LeetCode-2007. 从双倍数组中还原原数组【贪心 数组 哈希表 排序】 题目描述&#xff1a;解题思路一&#xff1a;排序 哈希表解题思路二&#xff1a;排序 队列解题思路三&#xff1a;消消乐 题目描述&#xff1a; 一个整数数组 original 可以转变成一个 双倍 数组 changed &…

使用Spring 完成转账业务添加日志功能

(完整的代码在文章附带文件中 , 文章里的代码仅作展示 , 可能有部分不完善 代码地址 :下载:https://javazhang.lanzn.com/i5oLI1vyiile 密码:1234 ) 任务目标 具体实现方法和心得 步骤1. 导入依赖项Spring依赖 , aop依赖,德鲁伊依赖,mybatis依赖 , mysql驱动 , mybatis-sprin…

jar包做成Windows Service 服务,不能访问网络映射磁盘

在Windows操作系统中&#xff0c;系统服务&#xff08;Services&#xff09;、计划任务&#xff08;Scheduled Tasks&#xff09;以及很多系统调用都是以SYSTEM系统账号进行操作的。用 net use 挂载&#xff0c;或者在文件管理器上直接挂载&#xff0c;挂载卷是以 Administrato…

在 ingress-nginx 负载均衡器上阻止特定路径

背景&#xff1a; 安全临时通知生产环境swagger的路径没屏蔽&#xff0c;正常思路是通过以下配置才能起作用&#xff0c;但是重启才能生效&#xff0c;又会影响用户使用。 springfox: documentation: # 总开关&#xff08;同时设置auto-startupfalse&#xff0c;否则/v3…

2020年海南职业院校技能大赛高职组

2020年海南职业院校技能大赛高职组“信息安全管理与评估”赛项任务书 信息安全管理与评估 网络系统管理 网络搭建与应用 云计算 软件测试 移动应用开发 任务书&#xff0c;赛题&#xff0c;解析等资料&#xff0c;知识点培训服务 添加博主wx&#xff1a;liuliu5488233 赛项时间…

go版本1.16.5 运行项目出现undefined: math.MaxInt报错

问题描述 go版本 go1.16.5 项目引用了 包go-sqlite3 v1.14.17 github.com/mattn/go-sqlite3 v1.14.17运行报错 # github.com/mattn/go-sqlite3 D:\GoPATH\pkg\mod\github.com\mattn\go-sqlite3v1.14.17\sqlite3_opt_serialize.go:41:26: undefined: math.MaxInt原因分析&…

华为 2024 届实习校园招聘-硬件通⽤/单板开发——第八套

华为 2024 届实习校园招聘-硬件通⽤/单板开发——第八套 部分题目分享&#xff0c;完整版带答案(有答案和解析&#xff0c;答案非官方&#xff0c;未仔细校正&#xff0c;仅供参考&#xff09;&#xff08;共十套&#xff09;获取&#xff08;WX:didadidadidida313&#xff0c…

理解相似性搜索(也称为语义搜索)的指南

了解人工智能相似性搜索 理解相似性搜索&#xff08;也称为语义搜索&#xff09;的指南&#xff0c;这是人工智能最新阶段的关键发现之一。 目录 一、说明二、向量三、人工智能中的向量四、将文本转换为向量五、创建向量嵌入六、存储向量嵌入七、相似性搜索八、执行相似性搜索…

OpenCV添加文字和水印------c++

添加文字 bool opencvTool::addText(cv::Mat& image, const std::string text, const cv::Point& position, double fontScale, cv::Scalar color, int thickness, int fontFace) {cv::putText(image, text, position, fontFace, fontScale, color, thickness);return…

3DTiles生产流程与规范

一篇19年整理的比较老的笔记了。更多精彩内容尽在数字孪生平台。 瓦片切分 标准的四叉树切分对于均匀分布的地理数据切片非常有效&#xff0c;但是这样均等的切分不适用于随机分布、不均匀分布的地理数据&#xff0c;当地理数据稀疏分布的时候&#xff0c;均等的四叉树就不再高…