基于 JSON 配置的 .NET 桌面应用自动更新方案

前言

在软件开发和维护过程中,程序更新一直是个绕不开的话题。一开始用最简单的方式------让用户手动下载新版本覆盖安装,但随着用户量增加、功能迭代加快,这种方式不仅效率低,还容易出错。一个轻量、可靠、配置灵活的自动更新机制变得尤为重要。

本文介绍一个简单可靠的 Windows 程序自动更新实用小工具,它不追求复杂的功能,而是专注于解决"如何让程序安静又稳妥地完成自我升级"这个问题。

项目介绍

一个基于 .NET 开发的轻量级程序更新框架,核心由两个部分组成:主程序集成逻辑 + 独立的升级执行程序(Upgrade.exe)。

它的设计思路很简单:每次启动主程序时,先检查是否有新版本;如果有,就调用 Upgrade.exe 完成文件替换,再重新启动主程序。整个过程对用户透明,且通过 JSON 配置驱动,无需硬编码更新地址或文件列表。

项目功能

主要功能围绕"对比---下载---替换---重启"展开

通过本地与服务器上的 UpLoadVersion.json 文件比对版本差异;

自动下载服务器上指定的更新文件(支持任意数量);

支持自动更新(IsAutoUpLoad=true)或手动确认更新;

更新完成后自动启动目标程序(可由配置指定,也可由主程序传入路径);

避免重复检测:升级失败或无更新时生成 NoUpgrade.ini,防止频繁弹窗。

项目特点

这个方案最大的特点是"轻"和"稳"。

它不需要数据库、不需要后台服务,只依赖一个 JSON 文件和一个独立的升级程序。配置完全外置,运维人员只需更新服务器上的 JSON 和文件,就能触发客户端升级。

同时,它巧妙利用环境变量判断是否在 Visual Studio 中调试,避免开发阶段误触发更新。

另外,通过传入主程序路径的方式,使得 ProgrmStartupDir 字段甚至可以留空,提升了灵活性。

项目使用

可以通过 JSON 文件进行更新和打开程序的一个更新程序。

UpLoadVersion.json 配置说明

UpLoadVersion.json 需要同时放置在程序安装目录和服务器更新目录中,是用于版本对比和更新控制的核心配置文件。

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 方法中:

csharp 复制代码
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 内容与服务器完全一致。

项目代码

自动更新

csharp 复制代码
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技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

相关推荐
c***87191 小时前
【update 更新数据语法合集】.NET开源ORM框架 SqlSugar 系列
开源·.net
唐青枫3 小时前
C# 原始字符串字面量全面解析:多行字符串终于优雅了!
c#·.net
缺点内向5 小时前
如何在 C# 中将 Excel 工作表拆分为多个窗格
开发语言·c#·.net·excel
夏霞12 小时前
c# 使用vs code 创建.net8.0以及.net6.0 webApi项目的教程
开发语言·c#·.net
追逐时光者13 小时前
C#/.NET/.NET Core优秀项目和框架2025年11月简报
后端·.net
Aevget14 小时前
界面控件DevExpress WinForms中文教程:Data Grid - 如何获取汇总值?
ui·.net·界面控件·winform·devexpress
时光追逐者16 小时前
C# 中 ?、??、??=、?: 、?. 、?[] 各种问号的用法和说明
开发语言·c#·.net·.net core
e***282919 小时前
四大.NET ORM框架深度对比:EF Core、SqlSugar、FreeSql与Dapper的性能、功能与适用场景
.net
czhc114007566320 小时前
WinForm 1130 monthCalendar NumbericUpDown Timer
c#·winform