之前用window窗体实现过一个升级功能,后来发现多个项目都需要升级功能,现改成可接收参数实现一种通用的exe.改用控制台方式实现这个升级功能,这样不仅实现了接收参数,升级程序体积也比原来的窗体形式更小。
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);
-
- }
-
- ///
- /// 下载新版本并验证版本号
- ///
- ///
- 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;
-
- }
-
-
- ///
- /// 安装
- ///
- 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;
- }
-
-
- ///
- /// 日记记录
- ///
- ///
- 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);
- }
-
- }
-
- ///
- /// http请求
- ///
- ///
- ///
- public static string request(string url)
- {
- using (WebClient client = new WebClient())
- {
- return client.DownloadString(url);
- }
- }
-
- ///
- /// 获取文件版本号
- ///
- ///
- ///
- 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;
- }
-
- ///
- /// 比较软件的版本号
- ///
- ///
- ///
- ///
- 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;
- }
- }
- }
因为升级是后台进行的,所以编译代码时 不要显示控制台,改一下:
如下图:

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

实现效果图如下:

查看更新日记
测试完美实现更新。