Skip to content

Latest commit

 

History

History
398 lines (314 loc) · 16 KB

File metadata and controls

398 lines (314 loc) · 16 KB
sidebar_position 3
title 入门实战手册

GeneralUpdate 入门实战手册

这篇手册面向第一次接触 GeneralUpdate 的开发者。目标不是一次讲完所有 API,而是让你从零开始,写完 Client → 写完 Upgrade → 用 Tools 生成配置 → 启动 Server → 一条命令跑通完整的"发现更新 → 下载 → 应用 → 回到新版本"闭环。

<iframe src="//player.bilibili.com/player.html?bvid=BV12P9dBiEEh&page=1" width="100%" height="480" style={{ borderRadius: '8px', border: 'none' }} allowFullScreen scrolling="no" />

更新流程总览

┌──────────────────────────────────────────────────────────────────────┐
│                     GeneralUpdate 完整更新流程                        │
└──────────────────────────────────────────────────────────────────────┘

  ① 版本检查               ② 下载包               ③ 应用更新
  ┌──────────┐           ┌──────────┐           ┌──────────┐
  │  Client  │──POST──→  │  Server  │           │ Upgrade  │
  │ (主程序)  │←─JSON───  │ (更新服务)│           │ (升级进程) │
  └────┬─────┘           └────┬─────┘           └────┬─────┘
       │                      │                      │
       │  POST /Upgrade/Verification               │                      │
       │  {version, platform} │                      │
       │ ────────────────────→│                      │
       │                      │                      │
       │  [{version, url,     │                      │
       │    hash, size}]      │                      │
       │ ←────────────────────│                      │
       │                      │                      │
       │  GET /File/Download  │                      │
       │ ────────────────────→│                      │
       │                      │                      │
       │  .zip packages       │                      │
       │ ←────────────────────│                      │
       │                      │                      │
       │  [写入 IPC 加密契约]   │                      │
       │  [启动 Upgrade.exe]   │                      │
       │ ────────────────────────────────────────────→│
       │                      │                      │
       │                      │    [读取 IPC 数据]    │
       │                      │    [校验 Hash]        │
       │                      │    [解压 → 覆盖]      │
       │                      │    [启动新版本 Client] │
       │                      │                      │
       │ ←────────────────────────────────────────────│
       │  [新版本运行中 ✓]     │                      │
       │                      │                      │
角色 在项目中的位置 负责什么
Client MyApp.exe(你自己的主程序) 检查更新 → 下载包 → 启动 Upgrade
Upgrade MyApp.Upgrade.exe(独立的升级进程) 校验 Hash → 解压覆盖 → 启动新版 Client
Server GeneralUpdate-Samples/src/Server 返回版本信息、接收更新报告、提供补丁下载
Tools GeneralUpdate.Tools 生成 generalupdate.manifest.json,串联 Client 与 Upgrade

Phase 1:环境准备

安装清单

要求 验证命令
.NET SDK 8.0+(推荐 10.0) dotnet --version
Git 任意版本 git --version

新建项目

打开终端,创建 Client 和 Upgrade 两个控制台项目:

dotnet new console -n MyApp
dotnet new console -n MyApp.Upgrade

cd MyApp
dotnet add package GeneralUpdate.Core

cd ../MyApp.Upgrade
dotnet add package GeneralUpdate.Core

预期结果:两个项目目录下都有 GeneralUpdate.Core 的 NuGet 引用。


Phase 2:集成 Client 代码

MyApp/Program.cs 中粘贴以下全部内容。Client 负责:检查更新 → 下载包 → 启动 Upgrade。

using GeneralUpdate.Core;
using GeneralUpdate.Core.Configuration;
using GeneralUpdate.Core.Event;

// ================================================================
// Client — 主程序入口,负责检测和下载更新
// ================================================================

// 只需设置 3 个 secret。MainAppName、ClientVersion、UpdateAppName
// 等身份字段由框架自动从 generalupdate.manifest.json 发现,无需手写。
var request = new UpdateRequest
{
    UpdateUrl    = "http://localhost:5000/Upgrade/Verification",
    ReportUrl    = "http://localhost:5000/Upgrade/Report",
    AppSecretKey = "dfeb5833-975e-4afb-88f1-6278ee9aeff6",
};

await new GeneralUpdateBootstrap()
    .SetConfig(request)
    .SetOption(Option.AppType, AppType.Client)
    .AddListenerUpdateInfo((_, e) =>
    {
        Console.WriteLine($"发现 {e.Info?.Body?.Count ?? 0} 个可用更新");
        if (e.Info?.Body != null)
        {
            foreach (var v in e.Info.Body)
                Console.WriteLine($"  v{v.Version}{v.Name} ({v.Size} bytes)");
        }
    })
    .AddListenerMultiDownloadStatistics((_, e) =>
    {
        Console.WriteLine($"\r下载: {e.ProgressPercentage:F0}% {e.Speed}");
    })
    .AddListenerMultiDownloadCompleted((_, e) =>
    {
        Console.WriteLine();
        Console.WriteLine($"下载 {(e.IsCompleted ? "✓ 完成" : "✗ 失败")}");
    })
    .AddListenerException((_, e) =>
    {
        Console.WriteLine($"异常: {e.Exception.Message}");
    })
    .LaunchAsync();

为什么只设 3 个参数?

ClientStrategy 在执行时会自动调用 AppMetadataDiscoverer.Discover(),从 generalupdate.manifest.json(Phase 4 用 Tools 生成)中读取身份字段并补全 UpdateRequest

字段 谁负责 说明
UpdateUrl 你写代码 Server 验证接口地址
ReportUrl 你写代码 Server 报告接口地址
AppSecretKey 你写代码 应用密钥
MainAppName 框架自动发现 从 manifest 读取
ClientVersion 框架自动发现 从 manifest 读取
UpdateAppName 框架自动发现 从 manifest 读取
ProductId 框架自动发现 从 manifest 读取
UpdatePath 框架自动发现 从 manifest 读取
InstallPath 默认值 AppDomain.CurrentDomain.BaseDirectory

如果你不想写 UpdateRequest,还可以用更简短的 SetSource()

await new GeneralUpdateBootstrap()
    .SetSource("http://localhost:5000/Upgrade/Verification",
               "dfeb5833-975e-4afb-88f1-6278ee9aeff6",
               "http://localhost:5000/Upgrade/Report")
    .SetOption(Option.AppType, AppType.Client)
    // ... listeners
    .LaunchAsync();

Client 不直接应用更新——下载完成后写 IPC 加密契约 → 启动 Upgrade → 自身退出。


Phase 3:集成 Upgrade 代码

MyApp.Upgrade/Program.cs 中粘贴以下全部内容。Upgrade 比 Client 更简单——不需要 SetConfig(),所有参数通过加密 IPC 文件从 Client 传入。

using GeneralUpdate.Core;
using GeneralUpdate.Core.Configuration;
using GeneralUpdate.Core.Event;

// ================================================================
// Upgrade — 独立的升级进程 (MyApp.Upgrade.exe)
// 无需 SetConfig(),参数由 Client 通过加密 IPC 文件传入
// ================================================================

await new GeneralUpdateBootstrap()
    .SetOption(Option.AppType, AppType.Upgrade)
    .AddListenerMultiDownloadStatistics((_, e) =>
    {
        Console.WriteLine($"\r应用补丁: {e.ProgressPercentage:F0}%");
    })
    .AddListenerMultiDownloadCompleted((_, e) =>
    {
        Console.WriteLine();
        Console.WriteLine($"补丁 {(e.IsCompleted ? "✓ 完成" : "✗ 失败")}");
    })
    .AddListenerException((_, e) =>
    {
        Console.WriteLine($"异常: {e.Exception.Message}");
    })
    .LaunchAsync();

Client vs Upgrade 差异

Client Upgrade
AppType AppType.Client AppType.Upgrade
SetConfig() ✅ 必须,设置服务器地址、版本等 ❌ 不需要,通过 IPC 从 Client 获取
职责 检查版本 → 下载包 → 启动 Upgrade Hash 校验 → 解压覆盖 → 启动新版 Client
谁启动谁 由用户直接启动 由 Client 进程自动启动

Phase 4:使用 Tools 生成项目结构

Client 和 Upgrade 代码写好后,用 Tools 的配置生成器(Config 标签页)一键 dotnet publish 并生成 generalupdate.manifest.json

操作步骤

打开 GeneralUpdate.Tools → 切换到 Config 标签页(配置生成器):

  1. Client .csproj Path:点击 Browse,选择 MyApp.csproj
  2. Upgrade .csproj Path:点击 Browse,选择 MyApp.Upgrade.csproj
  3. 点击 Analyze:Tools 解析两个 .csproj,自动填入:
    • MainAppName:来自 Client 项目的 AssemblyName(如 MyApp.exe
    • UpdateAppName:来自 Upgrade 项目的 AssemblyName(如 MyApp.Upgrade.exe
    • ClientVersion / UpgradeClientVersion:默认 1.0.0,按需修改
  4. 检查自动填入的字段,确认 UpdatePathupdate/(默认值)
  5. 点击 Generate Sample:Tools 依次执行:
    • dotnet publish Client → 输出到根目录
    • dotnet publish Upgrade → 输出到 update/ 子目录
    • 写入 generalupdate.manifest.json 到根目录

发布后的目录结构

Tools 可以帮助你一键 dotnet publish 并组装输出目录(通过 Config 标签页的 Sample Publisher)。最终结构如下:

publish/
├── MyApp.exe                   # Client publish 产物(Phase 2)
├── MyApp.dll
├── GeneralUpdate.Core.dll
├── generalupdate.manifest.json # Tools 生成,放根目录,框架自动发现
└── update/                     # Upgrade publish 产物(Phase 3),子目录名来自 manifest 的 updatePath
    ├── MyApp.Upgrade.exe
    └── MyApp.Upgrade.dll

注意MyApp.Upgrade.exe 不在根目录,而是在 update/ 子目录下。框架根据 manifest 的 updatePath 字段(默认 "update/")找到并启动它。

generalupdate.manifest.json 示例

{
  "mainAppName": "MyApp.exe",
  "clientVersion": "1.0.0.0",
  "updateAppName": "MyApp.Upgrade.exe",
  "upgradeClientVersion": "1.0.0.0",
  "appType": "Client",
  "productId": "2d974e2a-31e6-4887-9bb1-b4689e98c77a",
  "updatePath": "update/"
}

注意:manifest 只存身份/结构信息,不存 secret。 UpdateUrlReportUrlAppSecretKey 等敏感字段始终写在代码里,由 Phase 2 的 request.XXX = "..." 提供。


Phase 5:启动 Server

Client / Upgrade / manifest 全部就绪,启动 Server 准备端到端验证。

git clone https://github.com/GeneralLibrary/GeneralUpdate-Samples.git
cd GeneralUpdate-Samples/src/Server
dotnet run

预期输出:

╔══════════════════════════════════════════════════╗
║     GeneralUpdate Sample Upgrade Server          ║
╠══════════════════════════════════════════════════╣
║  Verification: http://localhost:5000/Upgrade/Verification
║  Report:       http://localhost:5000/Upgrade/Report
║  Download:     http://localhost:5000/File/Download/{hash}
║  Packages:     N version(s) loaded
╚══════════════════════════════════════════════════╝

Server 三端点速查

端点 方法 用途
/Upgrade/Verification POST Client 上报当前版本 → Server 返回可用更新列表
/Upgrade/Report POST Client 上报更新结果(成功 / 失败)
/File/Download/{hash} GET 下载更新包(支持 HTTP Range 断点续传)

Server 读取 wwwroot/packages/versions.json 中的包元数据并对外提供下载。

快速验证

curl -X POST http://localhost:5000/Upgrade/Verification \
  -H "Content-Type: application/json" \
  -d '{"Version":"1.0.0.0"}'

应返回包含可用更新版本的 JSON 响应。


Phase 6:端到端运行验证

# 终端 1 — 确保 Server 在运行
cd GeneralUpdate-Samples/src/Server && dotnet run

# 终端 2 — 运行 Client
cd MyApp && dotnet run

完整预期输出

Client:
  [UpdateInfo] 发现 1 个可用更新
    v2.0.0.0 — client_1.0.0_to_2.0.0 (xxxxx bytes)
  下载: 45% 1.2MB/s
  下载: 100%
  下载 ✓ 完成
  → 启动 MyApp.Upgrade.exe...

Upgrade:
  应用补丁: 50%
  应用补丁: 100%
  补丁 ✓ 完成
  → 启动 MyApp.exe (新版本)...

Client (新版本):
  MyApp v2.0.0.0 ✓

排查清单

现象 检查
Client 连不上 Server curl -X POST http://localhost:5000/Upgrade/Verification 确认 Server 在跑
返回"Already up to date" versions.json 中是否有比 ClientVersion 更高的版本
下载完成但未启动 Upgrade MyApp.Upgrade.exe 是否在 update/ 子目录下,manifest 的 updatePath 是否正确
Upgrade 报错退出 检查目录写入权限、杀毒软件是否拦截
端口被占用 修改 Server 启动参数 --Urls http://0.0.0.0:5001,同步修改 Client 的 UpdateUrl

下一步

跑通这条闭环后,建议按顺序深入阅读:

  1. GeneralUpdate.Core:更新策略、事件通知、静默更新、manifest 极简配置
  2. GeneralUpdate.Differential:差分算法、并行处理和 Clean/Dirty
  3. GeneralUpdate.Bowl:崩溃监控、备份和失败恢复
  4. GeneralUpdate.Tools:补丁包、Hash、OSS Config、Simulation 的完整操作指南

安装目录注意事项

更新过程中,应用程序需要对安装目录进行读写操作。为避免触发 Windows UAC(用户账户控制)弹窗,请将应用安装在以下非系统保护的目录:

推荐目录 路径示例
用户 AppData(推荐) C:\Users\<用户名>\AppData\Local\<你的应用名>\
用户主目录 C:\Users\<用户名>\<你的应用名>\
非系统盘自定义目录 D:\<你的应用名>\

不推荐的目录:

  • C:\Program Files\ — 需要管理员权限才能写入
  • C:\Program Files (x86)\ — 需要管理员权限才能写入
  • C:\Windows\ — 系统目录,禁止写入
  • 系统盘根目录(如 C:\) — 可能触发权限限制

提示:如果在更新时遇到"权限不足"或 UAC 弹窗,请检查应用是否安装在不推荐的目录中。将应用迁移到用户目录通常可以解决此问题。

示例仓库

仓库 地址
Samples(Server + Hub) GeneralUpdate-Samples
Tools(GUI 配置工具) GeneralUpdate.Tools
Core(NuGet 包源码) GeneralUpdate