前言
在軟件開發和維護過程中,程序更新一直是個繞不開的話題。一開始用最簡單的方式——讓用户手動下載新版本覆蓋安裝,但隨着用户量增加、功能迭代加快,這種方式不僅效率低,還容易出錯。一個輕量、可靠、配置靈活的自動更新機制變得尤為重要。
本文介紹一個簡單可靠的 Windows 程序自動更新實用小工具,它不追求複雜的功能,而是專注於解決"如何讓程序安靜又穩妥地完成自我升級"這個問題。
項目介紹
一個基於 .NET 開發的輕量級程序更新框架,核心由兩個部分組成:主程序集成邏輯 + 獨立的升級執行程序(Upgrade.exe)。
它的設計思路很簡單:每次啓動主程序時,先檢查是否有新版本;如果有,就調用 Upgrade.exe 完成文件替換,再重新啓動主程序。整個過程對用户透明,且通過 JSON 配置驅動,無需硬編碼更新地址或文件列表。
項目功能
主要功能圍繞"對比—下載—替換—重啓"展開
通過本地與服務器上的 UpLoadVersion.json 文件比對版本差異;
自動下載服務器上指定的更新文件(支持任意數量);
支持自動更新(IsAutoUpLoad=true)或手動確認更新;
更新完成後自動啓動目標程序(可由配置指定,也可由主程序傳入路徑);
避免重複檢測:升級失敗或無更新時生成 NoUpgrade.ini,防止頻繁彈窗。
項目特點
這個方案最大的特點是"輕"和"穩"。
它不需要數據庫、不需要後台服務,只依賴一個 JSON 文件和一個獨立的升級程序。配置完全外置,運維人員只需更新服務器上的 JSON 和文件,就能觸發客户端升級。
同時,它巧妙利用環境變量判斷是否在 Visual Studio 中調試,避免開發階段誤觸發更新。
另外,通過傳入主程序路徑的方式,使得 ProgrmStartupDir 字段甚至可以留空,提升了靈活性。
項目使用
可以通過 JSON 文件進行更新和打開程序的一個更新程序。
UpLoadVersion.json 配置説明
UpLoadVersion.json 需要同時放置在程序安裝目錄和服務器更新目錄中,是用於版本對比和更新控制的核心配置文件。
{
"UpLoadContent": "更新提示內容",
"UpLoadFileUrl": "更新的地址(帶輸出目錄的網站地址),例:http://localhost:8888/",
"ProgrmStartupDir": "更新完成後需要運行的程序",
"IsAutoUpLoad": true,
"UpLoadFiles": []
}
字段説明
-
UpLoadContent:更新時向用户展示的提示文本。 -
UpLoadFileUrl:服務器上更新文件所在的根 URL,需以/結尾。 -
ProgrmStartupDir:更新完成後要啓動的程序路徑(可為空,若啓動 Upgrade.exe 時傳入主程序路徑,則優先使用傳入值)。 -
IsAutoUpLoad:是否自動更新,設為true則無需用户點擊確認。 -
UpLoadFiles:包含待更新文件信息的數組,每項記錄文件名及其 MD5 值,用於比對是否需要下載。
IIS 發佈配置
1、添加網站,物理路徑指向你的最新程序更新目錄。
2、若訪問時出現 403 錯誤,請在 IIS 管理器中進入該網站 → 功能視圖 → "目錄瀏覽" → 點擊右側"啓用"。
生成服務器端 UpLoadVersion.json
將 UpLoadDemoXmlBuild.exe 複製到待發布的程序目錄中,運行後點擊"生成"按鈕,即可自動生成包含所有文件 MD5 的 UpLoadVersion.json。
C# 調用示例
將以下代碼放入 Program.cs 或 WPF 應用的 OnStartup 方法中:
string vsVersion = Environment.GetEnvironmentVariable("VisualStudioVersion");
if (string.IsNullOrEmpty(vsVersion))
{
string upIni = AppDomain.CurrentDomain.BaseDirectory + "NoUpgrade.ini";
if (!System.IO.File.Exists(upIni) && System.IO.File.Exists(AppDomain.CurrentDomain.BaseDirectory + "Upgrade.exe"))
{
Process.Start(AppDomain.CurrentDomain.BaseDirectory + "Upgrade.exe",
System.Reflection.Assembly.GetExecutingAssembly().Location);
Environment.Exit(0);
}
System.IO.File.Delete(upIni);
}
邏輯説明
-
通過
VisualStudioVersion環境變量判斷是否處於調試狀態,避免開發時觸發更新。 -
若存在
NoUpgrade.ini,表示上次檢測無更新,跳過本次檢查。 -
啓動
Upgrade.exe時傳入當前主程序路徑,作為更新完成後的啓動目標。 -
檢測結束後刪除
NoUpgrade.ini,確保下次啓動仍能檢查更新。
測試更新流程
1、初始狀態下,本地無更新文件。
2、運行程序,若檢測到服務器版本更新,則彈出提示(若 IsAutoUpLoad=true 則自動開始)。
3、下載完成後,Upgrade.exe 自動關閉,並啓動配置中指定或傳入的主程序。
4、更新後,本地的 UpLoadVersion.json 內容與服務器完全一致。
項目代碼
自動更新
private void UpLoadExcute(object obj)
{
Thread thread = new Thread(()=>{
if (obj!=null&&obj is System.Windows.Controls.FlowDocumentScrollViewer)
{
var uartDataFlowDocument = obj as System.Windows.Controls.FlowDocumentScrollViewer;
MsgScrollViewer = uartDataFlowDocument.Template.FindName("PART_ContentHost", uartDataFlowDocument) as System.Windows.Controls.ScrollViewer;
}
BtnIsEnabled = false;
ProgressBarVisiblity = Visibility.Visible;
BtnName = "正在更新...";
ContentTitle = "更新信息:";
UpLoadContent = "\r\n";
AppendMsg("正在比對本地系統與服務器的版本信息。");
ProgressBarValue = 4;
AppendMsg("需要更新"+ StaticModel.UpLoads.Count+"個文件!");
UpLoadDown(StaticModel.UpLoads);
AppendMsg("正在重新啓動程序...");
Thread.Sleep(2000);
//升級成功後刪除不檢測升級的文件
File.Delete(AppDomain.CurrentDomain.BaseDirectory + "NoUpgrade.ini");
if (!string.IsNullOrEmpty(StaticModel.MyUpLoadModel.ProgrmStartupDir))
{
Process.Start(StaticModel.MyUpLoadModel.ProgrmStartupDir);
Application.Current.Dispatcher.Invoke(new Action(() =>
{
Environment.Exit(0);
}));
}
else {
AppendMsg("沒有找到要啓動的程序路徑...");
}
//BtnIsEnabled = true;
//BtnName = "立 即 更 新";
});
thread.IsBackground = false;
thread.Start();
}
項目源碼
Gitee:https://gitee.com/sageinqi/UpLoadDemo
總結
本項目不是一個炫技型的框架,而是一個"解決問題就好"的務實工具。它沒有複雜的 UI,也不依賴雲服務,卻能有效支撐中小型桌面應用的持續交付需求。
對於那些不想引入 Electron autoUpdater 或商業更新服務的 .NET 團隊來説,這種基於文件比對 + JSON 配置的方案,既可控又易於維護。更重要的是,它把更新邏輯從主業務中剝離出來,降低了耦合度,也讓後續擴展(比如加簽名驗證、差分更新)成為可能。
關鍵詞
自動更新、JSON配置、MD5校驗、Upgrade.exe、IIS部署、.NET桌面應用、輕量級、程序升級、文件同步、無侵入
最後
如果你覺得這篇文章對你有幫助,不妨點個贊支持一下!你的支持是我繼續分享知識的動力。如果有任何疑問或需要進一步的幫助,歡迎隨時留言。
也可以加入微信公眾號[DotNet技術匠] 社區,與其他熱愛技術的同行一起交流心得,共同成長!