Skip to content

Repository files navigation

Moder.Update

一个 .NET 双进程自更新库。应用程序可以下载更新、启动独立的更新进程、退出,让更新进程原子性地替换文件并重启。

功能特性

  • 双进程更新模式 — 主程序下载更新、启动更新进程、退出;更新进程替换文件并重启主程序
  • Zstd 压缩 — 更新包使用 Zstd(通过 ZstdSharp)进行高效压缩
  • 原子性文件替换 — 在 Windows 上使用 ReplaceFile Win32 API 进行可靠的文件替换
  • 回滚支持 — 失败时自动备份和回滚
  • 链式更新路径 — 支持锚点包和累积包的版本链
  • SHA512 校验 — 文件级完整性检查
  • 无内置 HTTP — 消费者通过 IUpdateCatalogFetcher 提供自己的 HTTP 实现
  • 无界面 — 纯库,通过事件报告进度,无 UI

入门指南

安装

dotnet add package Moder.Update

基本用法

usingModer.Update;usingModer.Update.Compression;usingModer.Update.FileOperations;usingModer.Update.Models;usingModer.Update.Package;// 设置组件varcompressor=newZstdCompressor();varpackageReader=newZstdPackageReader(compressor);varfileService=newFileReplacementService();varprocessSpawner=newProcessSpawner();varupdateManager=newUpdateManager(packageReader,fileService,processSpawner);// 检查更新(使用你的 HTTP 客户端实现 IUpdateCatalogFetcher)varchecker=newUpdateChecker(myFetcher,updateManager);varresult=awaitchecker.CheckForUpdatesAsync("1.0.0");if(result.Status==UpdateCheckStatus.UpdateAvailable){foreach(varentryinresult.UpdatePath!){// 下载并应用每个更新包usingvarpackageStream=awaitmyFetcher.DownloadPackageAsync(entry.PackagePath);varupdateResult=awaitupdateManager.ApplyUpdateAsync(packageStream,newUpdateOptions{CurrentVersion="1.0.0",TargetDir=AppContext.BaseDirectory,EnableRollback=true});}// 启动更新进程并退出updateManager.PrepareRestart("Moder.Update.Updater.exe",options);Environment.Exit(0);}

实现 IUpdateCatalogFetcher

publicclassMyHttpFetcher:IUpdateCatalogFetcher{privatereadonlyHttpClient_client;privatereadonlystring_baseUrl;publicMyHttpFetcher(HttpClientclient,stringbaseUrl){_client=client;_baseUrl=baseUrl;}publicasyncTask<string>FetchCatalogAsync(CancellationTokenct=default){returnawait_client.GetStringAsync($"{_baseUrl}/catalog.json",ct);}publicasyncTask<Stream>DownloadPackageAsync(stringpackagePath,CancellationTokenct=default){returnawait_client.GetStreamAsync($"{_baseUrl}/{packagePath}",ct);}}

包格式

更新包使用以下二进制格式:

[4 字节: "MUP\0" 魔术头] + [Zstd 压缩的 tar 归档]

tar 归档包含:

  • manifest.json — 更新清单,包含版本信息、文件列表和校验和
  • 应用程序文件 — 完整替换文件(非差分)

更新目录

更新目录是一个 JSON 文件,服务于固定 URL:

{
"latestVersion": "2.0.0",
"minRequiredVersion": "1.0.0",
"lastUpdated": "2025-01-01T00:00:00Z",
"entries": [
{
"packagePath": "packages/1.1.0.zst",
"targetVersion": "1.1.0",
"minSourceVersion": "1.0.0",
"maxSourceVersion": "1.0.99",
"packageChecksum": "sha512hash...",
"fileCount": 5,
"compressedSize": 1024000,
"uncompressedSize": 2048000
}
]
}

更新进程

Moder.Update.Updater 是一个独立的控制台应用程序:

  1. 等待主应用程序进程退出
  2. 使用原子操作替换应用程序文件
  3. 重启主应用程序
Moder.Update.Updater --target-pid 1234 --target-path /path/to/app --staging-dir /path/to/staging

构建

dotnet build src/Moder.Update.sln
dotnet test src/Moder.Update.sln

打包

./scripts/pack.sh # Linux/macOS
scripts\pack.cmd # Windows

示例程序

提供了一个示例项目(Moder.Update.Demo)用于端到端测试更新流程。

前置要求

  • .NET 10.0 SDK 或更高版本
  • Windows 操作系统(该库使用 Win32 ReplaceFile API)

快速开始

# 1. 构建解决方案
dotnet build src/Moder.Update.sln
# 2. 创建测试包 (1.0.0 -> 1.1.0)
dotnet run --project src/Moder.Update.Demo -- \
--create-package 1.0.0 1.1.0 ./demo-app ./demo-packages
# 3. 将示例程序复制到测试目录
mkdir -p ./test-app
dotnet publish src/Moder.Update.Demo -c Release -o ./test-app
# 4. 运行 --check 查看更新状态
dotnet run --project ./test-app/Moder.Update.Demo.dll -- --check
# 5. 运行 --apply 应用更新并重启
dotnet run --project ./test-app/Moder.Update.Demo.dll -- --apply

示例程序命令

命令描述
--version显示当前版本
--check使用本地目录检查更新
--apply下载并应用更新包,然后重启
--create-package <from> <to> <source> <output>创建测试更新包

创建更新包

# Linux/macOS
./scripts/create-demo-package.sh 1.0.0 1.1.0 ./my-app ./demo-packages
# Windows
scripts\create-demo-package.cmd 1.0.0 1.1.0 .\my-app .\demo-packages

示例程序包位置

示例程序从相对于二进制文件的 ../../../demo-packages 目录查找更新包。该目录应包含:

  • catalog.json — 更新目录
  • *.zst — 更新包

许可协议

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages