前言
在實際開發(fā)中,WinForm 應(yīng)用程序的版本管理是一個常見需求。傳統(tǒng)的發(fā)布方式如 ClickOnce 雖然方便,但在某些場景下會出現(xiàn) DLL 文件缺失、更新失敗等問題。
本文介紹一種基于代碼實現(xiàn)的在線自動更新機制,通過讀取服務(wù)器上的版本信息與本地對比,判斷是否需要下載并更新程序。
該方案使用 JSON 配置文件進行版本控制,結(jié)合 ZIP 壓縮包實現(xiàn)更新邏輯,并利用 FastZip
進行解壓操作,適用于中小型項目快速集成自動更新功能。
實現(xiàn)思路
1、在 IIS 或 Web 服務(wù)器上部署更新包(ZIP 格式)和版本信息文件(JSON 格式)。
2、客戶端啟動時讀取本地版本號,并向服務(wù)器請求最新的版本信息。
3、比對版本號,若服務(wù)器版本高于本地,則觸發(fā)更新流程。
4、下載 ZIP 更新包后進行解壓替換原有文件。
5、重啟主程序完成更新。
這種方式避免了傳統(tǒng) ClickOnce 的兼容性問題,具有更高的靈活性和可控性。
系統(tǒng)結(jié)構(gòu)說明
1、版本配置文件(updates.json)
{
"latestversion": "3.0.3",
"downloadurl": "http://127.0.0.1:8091/FD3_WcsClient.zip",
"changelog": "更改日志",
"mandatory": true
}
2、對應(yīng)實體類 UpdateEntity
/// <summary>
/// 更新信息
/// </summary>
publicclassUpdateEntity
{
/// <summary>
/// 提供更新的版本號
/// </summary>
publicstring latestversion { get; set; }
/// <summary>
/// 更新包的下載路徑, 這里將需要更新的文件壓縮成zip文件
/// </summary>
publicstring downloadurl { get; set; }
/// <summary>
/// 更新日志
/// </summary>
publicstring changelog { get; set; }
/// <summary>
/// 是否是強制更新
/// </summary>
publicbool mandatory { get; set; }
}
3、窗體界面截圖(進度條展示更新狀態(tài))
?4、完整核心代碼以下為完整的 WinForm 自動更新窗體邏輯代碼:
using ICSharpCode.SharpZipLib.Zip;
using Newtonsoft.Json;
using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.Windows.Forms;
namespaceOnlineUpdateDemo
{
publicpartialclassForm1 : Form
{
privatestring NowVersion;
privatestring InstallPath;
privatestring StartPath;
private UpdateEntity updateEntity = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// 獲取當(dāng)前版本號
NowVersion = ConfigurationManager.AppSettings["Version"];
// 獲取解壓目錄
InstallPath = ConfigurationManager.AppSettings["InstallPath"];
// 獲取啟動路徑
StartPath = ConfigurationManager.AppSettings["StartPath"];
// 獲取更新配置
string UpdateEntityUrl = ConfigurationManager.AppSettings["UpdateEntityUrl"];
string updateJson = GetHtml(UpdateEntityUrl);
updateEntity = JsonConvert.DeserializeObject<UpdateEntity>(updateJson);
// 顯示版本信息
this.label_NowVersion.Text = NowVersion;
this.label_NextVersion.Text = updateEntity.latestversion;
if (string.Compare(updateEntity.latestversion, NowVersion) > 0)
{
label_message.Text = "有新版本";
if (updateEntity.mandatory)
{
Btn_Next_Click(null, null);
}
}
else
{
label_message.Text = "沒有更新版本了";
if (updateEntity.mandatory)
{
ShowLogin(); // 啟動主程序
}
}
}
private void Btn_Next_Click(object sender, EventArgs e)
{
try
{
WebClient wc = new WebClient();
wc.DownloadProgressChanged += Wc_DownloadProgressChanged;
Uri uri = new Uri(updateEntity.downloadurl);
if (!Directory.Exists(InstallPath))
{
Directory.CreateDirectory(InstallPath);
}
wc.DownloadFileAsync(uri, InstallPath + "FD3_WcsClient.zip");
}
catch (Exception er)
{
MessageBox.Show("下載失敗:" + er.Message);
}
}
private void Btn_Cancel_Click(object sender, EventArgs e)
{
this.Close();
this.Dispose();
}
private void Btn_Login_Click(object sender, EventArgs e)
{
ShowLogin();
}
private void Wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
Action act = () =>
{
this.progressBar1.Value = e.ProgressPercentage;
label_message.Text = "正在下載.....";
};
this.Invoke(act);
if (e.ProgressPercentage == 100)
{
label_message.Text = "正在解壓.....";
try
{
string zipFileName = InstallPath + "FD3_WcsClient.zip";
string targetDirectory = InstallPath;
var result = Compress(targetDirectory, zipFileName, "");
if (result == "Success!")
{
progressBar1.Value = 100;
this.label_message.Text = "更新完成";
// 更新配置文件中的版本號
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["Version"].Value = updateEntity.latestversion;
config.Save(ConfigurationSaveMode.Full);
ConfigurationManager.RefreshSection("appSettings");
ShowLogin(); // 啟動主程序
}
else
{
MessageBox.Show("更新失敗:" + result);
this.Close();
}
}
catch (Exception ex)
{
MessageBox.Show("解壓失?。? + ex.Message);
}
}
}
public string GetHtml(string url)
{
try
{
using (WebClient client = new WebClient())
{
byte[] data = client.DownloadData(url);
using (var ms = new MemoryStream(data))
using (var sr = new StreamReader(ms, Encoding.UTF8))
{
return sr.ReadToEnd();
}
}
}
catch (Exception)
{
MessageBox.Show("網(wǎng)絡(luò)連接失敗");
return"";
}
}
public string Compress(string DirPath, string ZipPath, string ZipPWD)
{
string state = "Fail!";
if (!Directory.Exists(DirPath) || !File.Exists(ZipPath)) return state;
try
{
FastZip fastZip = new FastZip();
fastZip.ExtractZip(ZipPath, DirPath, ZipPWD);
state = "Success!";
}
catch (Exception ex)
{
state += ", " + ex.Message;
}
return state;
}
public void ShowLogin()
{
System.Diagnostics.Process.Start(StartPath);
GC.Collect();
Application.Exit();
}
}
}
5、配置文件 App.config 內(nèi)容
<configuration>
<appSettings>
<!-- 當(dāng)前版本號 -->
<add key="Version" value="3.0.2" />
<!-- 版本配置文件地址 -->
<add key="UpdateEntityUrl" value="http://192.168.31.2:8091/updates.json" />
<!-- 解壓目錄 -->
<add key="InstallPath" value="D:/WCS_Project/" />
<!-- 主程序啟動路徑 -->
<add key="StartPath" value="D:/WCS_Project/福鼎物流控制系統(tǒng).exe" />
</appSettings>
</configuration>
總結(jié)
本文詳細(xì)介紹了如何使用 C# 編寫一個 WinForm 自動更新程序。通過比對遠(yuǎn)程 JSON 中的版本號,決定是否下載并解壓 ZIP 包進行更新。整個過程無需依賴 ClickOnce,更加靈活可靠,適合需要自定義更新策略的項目。
方案可擴展性強,未來可加入差分更新、斷點續(xù)傳、數(shù)字簽名驗證等高級功能,進一步提升系統(tǒng)的穩(wěn)定性和安全性。
關(guān)鍵詞
#WinForm、#自動更新、C#、#在線升級、#版本控制、#ZIP解壓、#JSON配置、#IIS部署、ICSharpCode.SharpZipLib、#FastZip
閱讀原文:原文鏈接
該文章在 2025/7/29 22:45:27 編輯過