使用GeneralUpdate实现.NET客户端程序自动更新
.NET客戶端程序自動更新
當我們在日常開發中編寫的客戶端程序需要部署在多臺主機上時,如果程序需要升級,那么一臺臺升級會非常麻煩,此時就可以使用本文的.NET客戶端程序自動更新技術。
本文所述的自動更新技術主要使用了開源的GeneralUpdate組件,可用于Winform/WPF/ConsoleApp等應用程序的自動更新。
GeneralUpdate組件是微軟的一位MVP負責開發和維護的,Gitee地址為:GeneralUpdate。作者提供的使用文檔和視頻有些過于簡單,而且不同版本還存在一定的兼容性問題,這些都沒有很好地解釋,所以初次接觸這個組件的開發人員可能會有點懵。筆者結合自己在項目中實際的使用情況,更加詳細地介紹一下該組件的使用方式。
文章目錄
- .NET客戶端程序自動更新
- 自動更新流程圖
- 代碼結構剖析
- Winform應用程序的自動更新實戰
- 更新組件的控制臺實現
- 客戶端調用
- 幾個槽點
- 總結
自動更新流程圖
鑒于原圖的說明不夠明確,筆者在上圖中使用紅色字體新增了說明。上圖中看上去是3個組件或服務的交互,但準確說是4個:
代碼結構剖析
上圖中以GeneralUpdate開頭的工程是自動更新功能的核心代碼,在nuget服務器上能看到各個工程的包。具體使用哪個包取決于你是想實現更新組件自更新還是更新客戶端程序還是編寫版本校驗服務,可參考框架README.md中的介紹。
這里要說明的是,上述組件不是向下兼容的!3.x.x版本的組件的很多方法都進行了更名,因此不能直接從2.x.x版本直接升級。
上圖中以AutoUpdate開頭的工程是對自動更新流程圖中3個主要組件的簡單實現:
- ConsoleApp:更新組件的控制臺版本DEMO(需要和文件服務器配合使用,引入了GeneralUpdate.Core)
- MauiApp-Sample:未仔細研究,不清楚
- MinimalService:客戶端版本校驗服務DEMO(引入了GeneralUpdate.AspNetCore)
- Test:更新組件自更新的WPF版本DEMO(需要和MinimalService配合使用,引入了GeneralUpdate.ClientCore)
- WpfApp:GeneralUpdate.Single包的使用DEMO,用于構建單例版本的更新組件(引入了GeneralUpdate.Single)
- WpfNet6-Sample:更新更新組件的WPF版本程序。
Winform應用程序的自動更新實戰
從上節的描述可知,如果我們不想編寫客戶端版本校驗服務,只想通過文件服務器來更新客戶端程序,那么我們只需要一個控制臺版本的更新組件即可,所以可參考ConsoleApp工程下的代碼。
更新組件的控制臺實現
說明:本示例使用的是GeneralUpdate.Core的2.1.6版本。因為Github上的源碼已升級到3.x.x版本,支持了.NET 6.0,但筆者電腦上的缺乏相關框架,無法編譯通過,所以檢出到了源碼的某次提交,這樣即使使用的時候出了問題也可以通過調試源碼的方式來解決。如果大家充分理解了本文的意思,直接安裝最新版本的nuget包也可以,直接參考最新版源碼的相關示例。
using System; using System.ComponentModel; using System.Diagnostics; using GeneralUpdate.Core; using GeneralUpdate.Core.Strategys; using GeneralUpdate.Core.Update; using ProgressChangedEventArgs = GeneralUpdate.Core.Update.ProgressChangedEventArgs;namespace AutoUpdate.ConsoleApp {class Program{static void Main(string[] args){// args = new []{// "1.0.1",// "1.0.2",// "",// "http://127.0.0.1:7000/client_v1.0.2.zip",// @"D:\Project",// "36aad55a19f85ee6e1fbdc26510a26c1"// };KillProcess("你的客戶端程序名,不用加exe");GeneralUpdateBootstrap bootstrap = new GeneralUpdateBootstrap();bootstrap.DownloadStatistics += OnDownloadStatistics;bootstrap.ProgressChanged += OnProgressChanged;bootstrap.Strategy<DefultStrategy>().Option(UpdateOption.Format, "zip").Option(UpdateOption.MainApp, "你的客戶端程序名,不用加exe").Option(UpdateOption.DownloadTimeOut, 60).RemoteAddress(args).Launch();Console.ReadKey();}private static void OnProgressChanged(object sender, ProgressChangedEventArgs e){if (e.Type == ProgressType.Updatefile){var str = $"當前更新第:{e.ProgressValue}個,更新文件總數:{e.TotalSize}";Console.WriteLine(str);}if (e.Type == ProgressType.Done){Console.WriteLine("更新完成");}if (e.Type == ProgressType.Fail){Console.WriteLine(e.Message);}}private static void OnDownloadStatistics(object sender, DownloadStatisticsEventArgs e){Console.WriteLine($"下載速度:{e.Speed},剩余時間:{e.Remaining.Minute}:{e.Remaining.Second}");}private static void KillProcess(string processName){foreach (var process in Process.GetProcesses()){if (!process.ProcessName.ToUpper().Contains(processName.ToUpper())) continue;try{process.Kill();process.WaitForExit();}catch (Win32Exception){}}}} }客戶端調用
Version version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; var ver = $"{version.Major}.{version.Minor}.{version.Build}"; //從數據庫獲取比當前程序集版本更高的版本信息 var versionInfo = TOSBll.Instance.GetLastUpdateVersionInfo(1, ver); if (versionInfo != null) {string para =$"{ver} {versionInfo.VERSION} \"\" {versionInfo.URL} {Environment.CurrentDirectory} {versionInfo.MD5}";ExecuteAsAdmin("AutoUpdate.ConsoleApp.exe", para);return; }private static void ExecuteAsAdmin(string fileName, string args) {Process proc = new Process();proc.StartInfo.FileName = fileName;proc.StartInfo.UseShellExecute = true;proc.StartInfo.Verb = "runas";proc.StartInfo.Arguments = args;proc.Start(); }由上述代碼可知,客戶端使用進程間通信的方式來啟動更新組件,并傳入更新參數信息。這里通過管理員權限啟動更新組件,以免更新失敗(組件在更新時需要把文件拷貝到系統的臨時目錄,更新成功后刪除,權限不足時會出錯)。不過筆者測試中發現這種方式啟動仍然失敗,還是通過右鍵AutoUpdate.ConsoleApp.exe程序并附加管理員權限才成功的。
幾個槽點
總結
雖然GeneralUpdate組件有一些不足,但相信經過本文的介紹,大家已經知道如何避坑來使用該組件。總體來說,該組件的功能還是蠻好用的。考慮到該組件只有作者一個人維護,其實已經做得蠻好了,還是要感謝作者的付出的。
總結
以上是生活随笔為你收集整理的使用GeneralUpdate实现.NET客户端程序自动更新的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 智慧组工: “一库一系统” 实现某市干部
- 下一篇: 资金管理