前言
在软件开发和维护过程中,程序更新一直是个绕不开的话题。一开始用最简单的方式——让用户手动下载新版本覆盖安装,但随着用户量增加、功能迭代加快,这种方式不仅效率低,还容易出错。一个轻量、可靠、配置灵活的自动更新机制变得尤为重要。
本文介绍一个简单可靠的 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桌面应用、#轻量级、#程序升级、#文件同步、#无侵入、#WPF、#WinForm
作者:小码编匠

.NET 桌面应用 (WPF/WinForm) 高效自动更新解决方案
开源免费 WPF 控件库 — 高颜值、功能齐全、支持工业场景
WPF 轻量级插件框架:动态菜单、浮动窗口、热加载 DLL,开箱即用
WPF 智能仓储上位机系统,集成数据采集与轻量级 MES 功能
C# + FFmpeg 一键转码,轻松解决海康视频网页播放难题
不用 GPU 也能跑的 WPF 视觉检测软件(Emgu CV + SQLite)
C# 工业级扫码难题破解,用微信实现精准扫码并自动填入任意应用
工业软件缺好 UI?这套 .NET 控件库从 IO 灯到圆角按钮全搞定
基于 .NET + Vue 3 的线路图绘制系统实战(含源码)
WinForm 下基于策略与工厂模式的 PLC 数据采集与监控系统
.NET 8 + Avalonia 跨平台简易校园信息管理系统的开发实战
C# + WPF + SuperSocket 开发面向工业自动化的 MES 系统
告别服务宕机,C# 看门狗守护你的 WinForm 与 Windows 服务
.NET 一款高效跨平台的自动更新工具(差异更新+热修复+自动升级)
面向工厂自动化的智能语音播报方案(基于.NET Windows服务)
工业自动化UI太难做?WPF 这套工业级控件方案真香(附源码)
工业自动化 WPF + Halcon 的模块化机器视觉解决方案
开源福利!八款 WPF + HandyControl 工业管理系统源码全公开
WinForm + Win32 API 自定义无边框窗口实战(工业软件必备)
基于 HslCommunication 的多端同步PLC远程监控系统
WinForm 数据采集实战:从串口通信到MES对接的轻量化解决方案
一个拒绝过度设计的 .NET 快速开发框架:开箱即用,专注"干活"
WinForm + SunnyUI 与 MQTTnet 实现智能可视化的火警联动大屏系统
.NET 9 + WPF + Halcon 构建工业视觉流程框架:从架构设计到落地实践
WinForm 高分屏适配难题?一款强大的控件自适应缩放工具
觉得有收获?不妨分享让更多人受益
关注「DotNet技术匠」,共同提升技术实力

