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

 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.mzph.cn/diannao/3115.shtml

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

相关文章

河道采砂执法监管信息化平台:科技赋能,智慧监管

随着信息技术的飞速发展&#xff0c;信息化平台已经成为提升行业监管效率和水平的重要工具。河道采砂作为水利资源管理的重要环节&#xff0c;其执法监管同样需要与时俱进&#xff0c;利用先进技术手段提升监管效能。河道采砂执法监管信息化平台便是这一背景下的产物&#xff0…

从底层分析并详解SpringAOP底层实现

首先分析AOP的实现 首先切面&#xff08;Advisor&#xff09;由通知(Advice)和切点(Pointcut)组成 包括前置通知后置通知等等最终都会被转化为实现 MethodInterceptor 接口的环绕通知 先看一段代码了解一下是aop是怎么运作的 首先定义了两个类实现了MethodInterceptor接口&…

Unity HDRP Water Surface 水系统 基础教程

Unity HDRP Water Surface 水系统 基础教程 Unity Water SurfaceUnity 项目创建Unity Water Surface&#xff1a;Ocean&#xff08;海洋&#xff09;简介Ocean&#xff1a;Transform、GeneralOcean&#xff1a;Simulation&#xff08;仿真模拟&#xff09;Ocean&#xff1a;Sim…

C++之STL-String

目录 一、STL简介 1.1 什么是STL 1.2 STL的版本 1.3 STL的六大组件 ​编辑 1.4 STL的重要性 二、String类 2.1 Sting类的简介 2.2 string之构造函数 2.3 string类对象的容量操作 2.3.1 size() 2.3.2 length() 2.3.3 capacity() 2.3.4 empty() 2.3.5 clear() 2.3.6…

【IDEA】在IntelliJ IDEA中导入Eclipse项目:详细指南

IntelliJ IDEA和Eclipse是两款常用的集成开发环境&#xff08;IDE&#xff09;&#xff0c;在软件开发中经常会遇到需要在它们之间迁移项目的情况。本文将重点介绍如何在IntelliJ IDEA中导入Eclipse项目&#xff0c;以帮助开发者顺利地迁移他们的项目&#xff0c;并在IntelliJ …

echarts 堆叠柱状图 顶部添加合计

堆叠有3个&#xff0c;后面加了一个对象显示顶部的数据&#xff0c; 其实主要的代码还是在series 的第四项&#xff0c;需要注意的是 series的第四项中的data需要为 data: [0, 0, 0] 顶部的统计才能显示出来 增加的代码如下 {name: 综合,type: bar,stack: total,label: {sh…

【Java框架】SpringMVC(三)——异常处理,拦截器,文件上传,SSM整合

目录 异常处理解释局部异常处理全局异常 拦截器拦截器介绍作用:拦截器和过滤器之间的区别拦截器执行流程代码实现补充 文件上传依赖配置MultipartResolver编写文件上传表单页APIMultipartFileFile.separator必须对上传文件进行重命名代码示例 SpringMVC文件上传流程多文件上传 …

AWS制作WordPress在国内外的利弊?

AWS作为全球领先的云计算服务供应商&#xff0c;为WordPress提供了强大且灵活的托管环境&#xff0c;使用AWS来搭建和运行WordPress无疑是个不错的选择。即便如此使用AWS制作还是会有些许利弊&#xff0c;九河云作为AWS的合作伙伴来为读者们仔细探讨AWS在WordPress的利弊。 利&…

学python的第十九天

网络通信和访问数据库 1.1 基本的网络知识 TCP/IP IP是低级的路由协议&#xff0c;它将数据拆分在许多小的数据包中&#xff0c;并通过网络将他们发送到某一特定地址&#xff0c;但无法保证所有包都抵达目的地&#xff0c;也不能保证包按顺序抵达 TCP&#xff08;传输控制协议…

深度学习系列65:数字人openHeygen详解

1. 主流程分析 从inference.py函数进入&#xff0c;主要流程包括&#xff1a; 1&#xff09; 使用cv2获取视频中所有帧的列表&#xff0c;如下&#xff1a; 2&#xff09;定义Croper。核心代码为69行&#xff1a;full_frames_RGB, crop, quad croper.crop(full_frames_RGB)。…

Android MVVM架构 + Retrofit完成网络请求

关于Retrofit&#xff0c;这个应该不是一个很新颖的东西了&#xff0c;简单过一下吧 1.由Square公司开发&#xff0c;基于Type-safe的REST客户端。 2.使用注解来定义API接口&#xff0c;使得HTTP请求变得简洁且易于维护。 3.支持同步和异步请求&#xff0c;可与RxJava、Corouti…

【安卓13】解决带GMS编译报super分区空间不足错误

1、错误信息 2、解决方案 不同供应商修改分区大小的文件路径不一样&#xff0c;但是万变不离其宗&#xff0c;根据报错信息全局搜索关键词BOARD_SUPER_PARTITION_SIZE 这里以RK供应商和AML供应商修改为例&#xff1a; &#xff08;1&#xff09;RK改法&#xff1a; 根目录下…

全光谱灯对人体的危害?谨记全光谱灯选购要避开的四大套路

全光谱灯对人体的危害有多大&#xff1f;近年来网上关于护眼台灯对视力有害的言论有很多&#xff0c;引发了很多人空前的关注&#xff0c;事实上这未必是一件坏事&#xff0c;因为随着护眼台灯的热度持续上涨&#xff0c;市面上浑水摸鱼的行为增多了不少&#xff0c;有着不少劣…

STM32H7使用FileX库BUG,SD卡挂载失败

问题描述&#xff1a; 使用STM32H7ThreadXFileX&#xff0c;之前使用swissbit牌的存储卡可正常使用&#xff0c;最近项目用了金士顿的存储卡&#xff0c;发现无法挂载文件系统。 原因分析&#xff1a; 调试过程发现&#xff0c;关闭D-Cache可以挂载使用exfat文件系统。 File…

一文看够,植物线粒体基因组分析套路

线粒体堪称生命活动的“能量供给站”&#xff0c;植物线粒体是线粒体基因组研究中难度最高的&#xff0c;其基因组大小差异较大&#xff0c;100kb-10Mb&#xff0c;大部分由非编码DNA序列组成&#xff0c;且有许多同源序列&#xff0c;占基因组总长的2%-60%&#xff0c;基因间区…

制作github.io学术个人主页

制作如图的学术个人主页。About me - Xianwen Ling’s Blog 学术个人主页是一个学者展示个人学术成果和研究方向的重要工具。个人主页可以集中展示学者的研究论文、出版物、演讲和发布的项目等学术成果&#xff0c;这样其他人可以更方便地了解和评估学者的研究贡献。个人主页可…

Maven 安装及配置教程(Windows)【安装】

文章目录 一、 下载1. 官网下载2. 其它渠道 二、 安装三、 配置四、 验证五、 本地仓储配置六、 配置镜像七、 配置JDK八、完整配置九、常用命令十、IDEA 中配置 Maven1. 配置当前项目2. 配置新建 / 新打开 项目 软件 / 环境安装及配置目录 一、 下载 1. 官网下载 安装地址&a…

书生·浦语大模型第二期实战营第七节-OpenCompass 大模型评测实战 笔记和作业

来源&#xff1a; 视频教程&#xff1a;https://www.bilibili.com/video/BV1Pm41127jU/?spm_id_from333.788&vd_sourcef4a51f7f5a63e756f73ad0dff318c1a3 文字教程&#xff1a;https://github.com/InternLM/Tutorial/blob/camp2/opencompass/readme.md 作业来源&#x…

【Hadoop】- MapReduce YARN 初体验[9]

目录 提交MapReduce程序至YARN运行 1、提交wordcount示例程序 1.1、先准备words.txt文件上传到hdfs&#xff0c;文件内容如下&#xff1a; 1.2、在hdfs中创建两个文件夹&#xff0c;分别为/input、/output 1.3、将创建好的words.txt文件上传到hdfs中/input 1.4、提交MapR…

HotSpot JVM 中的应用程序/动态类数据共享

0.前言 本文的目的是详细讨论 HotSpot JVM 自 JDK 1.5 以来提供的一项功能&#xff0c;该功能可以减少启动时间&#xff0c;但如果在多个 JVM 之间共享相同的类数据共享 (CDS) 存档&#xff0c;则还可以减少内存占用。 1.类数据共享 (CDS) CDS 的想法是使用特定格式将预处理…