diff --git a/website/docs/doc/GeneralUpdate.Bowl.md b/website/docs/doc/GeneralUpdate.Bowl.md index 44e0b4f..4ecc369 100644 --- a/website/docs/doc/GeneralUpdate.Bowl.md +++ b/website/docs/doc/GeneralUpdate.Bowl.md @@ -4,325 +4,301 @@ sidebar_position: 3 # GeneralUpdate.Bowl -## 组件概览 +## 简介 -**GeneralUpdate.Bowl** 是一个独立的进程监控组件,在升级流程结束前启动,负责启动主客户端应用程序并监控其运行状态。该组件提供了完整的崩溃监控和诊断能力,当被监控的应用程序发生异常时,会自动导出Dump文件、驱动信息、系统信息和事件日志,帮助开发者快速定位问题。 +**GeneralUpdate.Bowl** 是升级完成后的启动守护组件。它不负责下载、解压或替换升级包,而是在新版本文件落地、主程序即将启动或已经启动时,监控目标进程是否在启动阶段崩溃。如果捕获到崩溃,它会生成 Dump、写出失败报告、导出诊断信息,并在升级模式下把备份目录恢复回安装目录,避免用户一直停留在不可启动的新版本上。 + +**命名空间:** `GeneralUpdate.Bowl` -**命名空间:** `GeneralUpdate.Bowl` **程序集:** `GeneralUpdate.Bowl.dll` -```csharp -public sealed class Bowl -``` +**当前主要入口:** `new Bowl().LaunchAsync(BowlContext context, CancellationToken ct = default)` ---- +## 阅读导航 -## 核心特性 +| 主题 | 适合解决的问题 | +| --- | --- | +| [生命周期位置](#生命周期位置) | Bowl 应该在升级流程的哪个阶段运行 | +| [快速接入](#快速接入) | 用当前 `BowlContext` API 完成一次监控 | +| [崩溃检测与恢复流程](#崩溃检测与恢复流程) | 崩溃后组件具体做了什么 | +| [BowlContext 参数](#bowlcontext-参数) | 每个配置项的含义和推荐值 | +| [输出文件](#输出文件) | Dump、失败报告、系统诊断、追踪日志在哪里 | +| [事件回调](#事件回调) | 如何在崩溃时上传报告或通知用户 | +| [日志开关](#日志开关) | 如何为了性能关闭组件追踪日志 | +| [平台差异](#平台差异) | Windows、Linux、macOS 的监控能力差异 | +| [恢复场景](#恢复场景) | 一次真实升级失败回滚过程 | +| [旧 API 迁移](#旧-api-迁移) | 从 `MonitorParameter` 迁移到 `BowlContext` | -### 1. 进程监控 -- 实时监控目标应用程序的运行状态 -- 自动检测进程崩溃和异常退出 +## 生命周期位置 -### 2. 崩溃诊断 -- 自动生成Dump文件(.dmp)用于崩溃分析 -- 导出详细的系统和驱动信息 -- 收集Windows系统事件日志 +在 GeneralUpdate 的完整升级链路中,Bowl 位于**文件替换完成之后、用户正式使用新版本之前**: -### 3. 版本化管理 -- 按版本号分类存储故障信息 -- 支持升级和正常两种工作模式 +1. Core 获取更新信息、下载包、校验并应用更新。 +2. Core/Upgrade 进程准备启动主程序。 +3. Bowl 作为守护逻辑启动,附加到目标进程并等待启动期异常。 +4. 主程序正常启动:没有 Dump 产生,Bowl 返回本次监控结果。 +5. 主程序启动崩溃:Bowl 进入故障处理管线,生成诊断文件并按配置恢复备份。 ---- +在当前 Core 代码中,Windows 的 `UpdateStrategy` 会在更新完成后通过 OS 策略启动主程序,并在配置了 Bowl 进程名时一并启动 Bowl 辅助进程。Linux/macOS 侧 Core 策略没有同等的 Bowl helper 自动启动能力,通常需要由你的启动器、服务脚本或独立进程显式调用 `LaunchAsync`。 -## 快速开始 +:::tip +Bowl 是“升级后健康检查与回滚保护”,不是固件恢复、系统还原或升级包安装器。它处理的是应用启动崩溃后的诊断与应用目录级备份恢复。 +::: -### 安装 +## 快速接入 -通过 NuGet 安装 GeneralUpdate.Bowl: +### 安装 ```bash dotnet add package GeneralUpdate.Bowl ``` -### 初始化与使用 +### 升级模式监控 -以下示例展示了如何使用 Bowl 组件监控应用程序: +升级模式适合放在升级程序或 Bowl helper 中运行。关键点是:`BackupDirectory` 指向升级前保留的备份,`TargetPath` 指向当前安装目录,`ExtendedField` 填本次升级版本号。 ```csharp using GeneralUpdate.Bowl; -using GeneralUpdate.Bowl.Strategys; +var version = "2.0.0"; var installPath = AppDomain.CurrentDomain.BaseDirectory; -var lastVersion = "1.0.0.3"; -var processInfo = new MonitorParameter + +var context = new BowlContext { - ProcessNameOrId = "YourApp.exe", - DumpFileName = $"{lastVersion}_fail.dmp", - FailFileName = $"{lastVersion}_fail.json", + ProcessNameOrId = "MyApp.exe", + DumpFileName = $"{version}_fail.dmp", + FailFileName = $"{version}_fail.json", TargetPath = installPath, - FailDirectory = Path.Combine(installPath, "fail", lastVersion), - BackupDirectory = Path.Combine(installPath, lastVersion), - WorkModel = "Normal" // 使用 Normal 模式独立监控 + FailDirectory = Path.Combine(installPath, "fail", version), + BackupDirectory = Path.Combine(installPath, version), + WorkModel = "Upgrade", + ExtendedField = version, + TimeoutMs = 30_000, + DumpType = DumpType.Full, + AutoRestore = true, + OnCrash = (info, ct) => + { + Console.WriteLine($"Crash dump: {info.DumpFilePath}"); + Console.WriteLine($"Crash report: {info.CrashReportPath}"); + return Task.CompletedTask; + } }; -Bowl.Launch(processInfo); -``` - ---- - -## 核心 API 参考 -### Launch 方法 +BowlResult result = await new Bowl().LaunchAsync(context); -启动进程监控功能。 - -**方法签名:** - -```csharp -public static void Launch(MonitorParameter? monitorParameter = null) -``` - -**参数:** - -#### MonitorParameter 类 - -```csharp -public class MonitorParameter -{ - /// - /// 被监控的目录 - /// - public string TargetPath { get; set; } - - /// - /// 导出异常信息的目录 - /// - public string FailDirectory { get; set; } - - /// - /// 备份目录 - /// - public string BackupDirectory { get; set; } - - /// - /// 被监控进程的名称或ID - /// - public string ProcessNameOrId { get; set; } - - /// - /// Dump 文件名 - /// - public string DumpFileName { get; set; } - - /// - /// 升级包版本信息(.json)文件名 - /// - public string FailFileName { get; set; } - - /// - /// 工作模式: - /// - Upgrade: 升级模式,主要用于与 GeneralUpdate 配合使用,内部逻辑处理,默认模式启动时请勿随意修改 - /// - Normal: 正常模式,可独立使用监控单个程序,程序崩溃时导出崩溃信息 - /// - public string WorkModel { get; set; } = "Upgrade"; +if (result.DumpCaptured && result.Restored) +{ + Console.WriteLine("The upgraded version crashed and the backup was restored."); } ``` ---- - -## 实际使用示例 +### 独立监控模式 -### 示例 1:独立模式监控应用 +`Normal` 模式只做崩溃捕获、报告输出和回调通知,不会自动恢复备份,也不会写入 `UpgradeFail` 失败版本标记。 ```csharp -using GeneralUpdate.Bowl; -using GeneralUpdate.Bowl.Strategys; - -// 配置监控参数 -var installPath = AppDomain.CurrentDomain.BaseDirectory; -var currentVersion = "1.0.0.5"; - -var monitorConfig = new MonitorParameter +var context = new BowlContext { - ProcessNameOrId = "MyApplication.exe", - DumpFileName = $"{currentVersion}_crash.dmp", - FailFileName = $"{currentVersion}_crash.json", - TargetPath = installPath, - FailDirectory = Path.Combine(installPath, "crash_reports", currentVersion), - BackupDirectory = Path.Combine(installPath, "backups", currentVersion), - WorkModel = "Normal" // 独立监控模式 + ProcessNameOrId = "MyWorker.exe", + DumpFileName = "startup_fail.dmp", + FailFileName = "startup_fail.json", + TargetPath = AppDomain.CurrentDomain.BaseDirectory, + FailDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fail", "startup"), + BackupDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "backup"), + WorkModel = "Normal", + TimeoutMs = 15_000, + DumpType = DumpType.Mini, + AutoRestore = false }; -// 启动监控 -Bowl.Launch(monitorConfig); +BowlResult result = await new Bowl().LaunchAsync(context); ``` -### 示例 2:结合 GeneralUpdate 使用 - -```csharp -using GeneralUpdate.Bowl; -using GeneralUpdate.Bowl.Strategys; +## 崩溃检测与恢复流程 -// 在升级完成后启动 Bowl 监控 -var installPath = AppDomain.CurrentDomain.BaseDirectory; -var upgradedVersion = "2.0.0.1"; +`LaunchAsync` 的核心判断非常直接:平台策略先启动监控工具,监控工具输出到 `FailDirectory`;Bowl 再检查 `{FailDirectory}/{DumpFileName}` 是否存在。存在 Dump 就认为启动阶段发生了崩溃。 -var upgradeMonitor = new MonitorParameter -{ - ProcessNameOrId = "UpdatedApp.exe", - DumpFileName = $"{upgradedVersion}_fail.dmp", - FailFileName = $"{upgradedVersion}_fail.json", - TargetPath = installPath, - FailDirectory = Path.Combine(installPath, "fail", upgradedVersion), - BackupDirectory = Path.Combine(installPath, upgradedVersion), - WorkModel = "Upgrade" // 升级模式 -}; +| 阶段 | 当前实现 | +| --- | --- | +| 准备监控 | 根据操作系统选择 `WindowsBowlStrategy`、`LinuxBowlStrategy` 或 `MacBowlStrategy` | +| 捕获异常 | Windows 使用 ProcDump;Linux 尝试安装并调用 ProcDump;macOS 使用 `lldb` 基础能力 | +| 判断崩溃 | 检查 `FailDirectory` 中是否生成指定 Dump 文件 | +| 生成报告 | 写出 `{version}_fail.json`,包含监控参数和监控工具输出 | +| 导出诊断 | Windows 调用 `Applications/Windows/export.bat` 导出驱动、系统信息和最近系统日志 | +| 恢复备份 | 仅当 `WorkModel == "Upgrade"` 且 `AutoRestore == true` 时,把 `BackupDirectory` 覆盖复制回 `TargetPath` | +| 标记失败版本 | 升级模式下写入 `UpgradeFail = ExtendedField`,Core 后续会跳过小于等于该失败版本的更新 | +| 通知业务 | 如果配置了 `OnCrash`,传出 Dump 路径、报告路径、版本号和退出码 | -Bowl.Launch(upgradeMonitor); -``` +`TimeoutMs` 是监控子进程的等待上限。超时且没有 Dump 时,Bowl 不会执行恢复管线;此时更应该关注 `DumpCaptured` 是否为 `true`,而不是只看 `Success`。 ---- +## BowlContext 参数 -## 崩溃信息捕获 +| 参数 | 说明 | 建议 | +| --- | --- | --- | +| `ProcessNameOrId` | 要监控的进程名或 PID | Windows 可使用进程名;Linux 上更建议传 PID | +| `DumpFileName` | Dump 文件名 | 推荐包含版本号,例如 `2.0.0_fail.dmp` | +| `FailFileName` | 崩溃报告 JSON 文件名 | 推荐和 Dump 同版本,例如 `2.0.0_fail.json` | +| `TargetPath` | 当前应用安装根目录 | 恢复备份时会覆盖复制到这里 | +| `FailDirectory` | 故障文件输出目录 | 推荐 `Path.Combine(TargetPath, "fail", version)` | +| `BackupDirectory` | 升级前备份目录 | `AutoRestore` 打开时必须确保目录存在且内容完整 | +| `WorkModel` | `Upgrade` 或 `Normal` | 升级后回滚用 `Upgrade`;普通崩溃采集用 `Normal` | +| `ExtendedField` | 扩展字段,当前主要存版本号 | 升级模式下会写入 `UpgradeFail` | +| `TimeoutMs` | 监控子进程超时时间 | 默认归一化为 30000 ms,按应用启动耗时调大 | +| `DumpType` | `Full`、`Mini`、`Heap` | 生产环境可先用 `Mini` 降低体积;疑难问题用 `Full` | +| `AutoRestore` | 是否自动恢复备份 | 升级模式要显式设置为 `true` | +| `OnCrash` | 单次崩溃回调 | 适合上传报告、通知用户、写入业务日志 | -当检测到崩溃时,以下文件将在运行目录中生成: +### DumpType 选择 -- 📒 **Dump 文件** (`x.0.0.*_fail.dmp`) -- 📒 **升级包版本信息** (`x.0.0.*_fail.json`) -- 📒 **驱动信息** (`driverInfo.txt`) -- 📒 **操作系统/硬件信息** (`systeminfo.txt`) -- 📒 **系统事件日志** (`systemlog.evtx`) +| 类型 | Windows ProcDump 参数 | 特点 | +| --- | --- | --- | +| `Full` | `-ma` | 信息最完整,文件最大,适合难复现问题 | +| `Mini` | `-mm` | 文件更小,生成更快,适合生产默认采集 | +| `Heap` | `-mh` | 带堆信息的小型 Dump,介于 Mini 和 Full 之间 | -这些文件将按版本号分类导出到 "fail" 目录中。 +## 输出文件 -![崩溃文件](imgs/crash.jpg) +一次升级失败后,推荐按版本存放所有故障文件: -### 1. Dump 文件 - -Dump 文件包含崩溃时刻的内存快照,可用于调试分析: +```text +MyApp/ + fail/ + 2.0.0/ + 2.0.0_fail.dmp + 2.0.0_fail.json + driverInfo.txt + systeminfo.txt + systemlog.evtx + Logs/ + generalupdate-trace 2026-01-01.log +``` -![Dump文件](imgs/dump.png) +| 文件 | 来源 | 内容 | +| --- | --- | --- | +| `{version}_fail.dmp` | ProcDump 或 lldb | 崩溃现场内存快照 | +| `{version}_fail.json` | `CrashReporter` | `BowlContext` 映射参数和监控工具输出行 | +| `driverInfo.txt` | Windows `driverquery` | Windows 驱动列表 | +| `systeminfo.txt` | Windows `systeminfo` | OS、硬件、内存等系统信息 | +| `systemlog.evtx` | Windows `wevtutil` | 最近一天 Windows System 事件日志 | +| `Logs/generalupdate-trace yyyy-MM-dd.log` | `GeneralTracer` | Bowl 自身运行追踪日志 | -### 2. 版本信息文件 +非 Windows 平台当前不会导出 `driverInfo.txt`、`systeminfo.txt`、`systemlog.evtx`,但仍会尽量生成 Dump 和失败 JSON。 -JSON 格式的详细崩溃报告,包含参数配置和 ProcDump 输出: +失败 JSON 的结构来自当前 `CrashReporter`: ```json { -"Parameter": { -"TargetPath": "D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\", -"FailDirectory": "D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\fail\\1.0.0.3", -"BackupDirectory": "D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\1.0.0.3", -"ProcessNameOrId": "JsonTest.exe", -"DumpFileName": "1.0.0.3_fail.dmp", -"FailFileName": "1.0.0.3_fail.json", -"WorkModel": "Normal", -"ExtendedField": null -}, -"ProcdumpOutPutLines": [ - "ProcDump v11.0 - Sysinternals process dump utility", - "Copyright (C) 2009-2022 Mark Russinovich and Andrew Richards", - "Sysinternals - www.sysinternals.com", - "Process: JsonTest.exe (19712)", - "Process image: D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\JsonTest.exe", "CPU threshold: n/a", - "Performance counter: n/a", "Commit threshold: n/a", - "Threshold seconds: n/a", "Hung window check: Disabled", "Log debug strings: Disabled", - "Exception monitor: Unhandled", "Exception filter: [Includes]", - " *", - " [Excludes]", - "Terminate monitor: Disabled", - "Cloning type: Disabled", - "Concurrent limit: n/a", - "Avoid outage: n/a", - "Number of dumps: 1", - "Dump folder: D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\fail\\1.0.0.3\\", - "Dump filename/mask: 1.0.0.3_fail", - "Queue to WER: Disabled", "Kill after dump: Disabled", - "Press Ctrl-C to end monitoring without terminating the process.", - "[19:05:23] Exception: E0434352.CLR", "[19:05:23] Unhandled: E0434352.CLR", - "[19:05:23] Dump 1 initiated: D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\fail\\1.0.0.3\\1.0.0.3_fail.dmp", - "[19:05:23] Dump 1 writing: Estimated dump file size is 62 MB.", - "[19:05:23] Dump 1 complete: 62 MB written in 0.1 seconds", - "[19:05:23] Dump count reached."] + "Parameter": { + "TargetPath": "C:\\Program Files\\MyApp", + "FailDirectory": "C:\\Program Files\\MyApp\\fail\\2.0.0", + "BackupDirectory": "C:\\Program Files\\MyApp\\2.0.0", + "ProcessNameOrId": "MyApp.exe", + "DumpFileName": "2.0.0_fail.dmp", + "FailFileName": "2.0.0_fail.json", + "WorkModel": "Upgrade", + "ExtendedField": "2.0.0" + }, + "ProcdumpOutPutLines": [ + "ProcDump v11.0 - Sysinternals process dump utility", + "[10:00:03] Dump 1 initiated: C:\\Program Files\\MyApp\\fail\\2.0.0\\2.0.0_fail.dmp", + "[10:00:03] Dump count reached." + ] } ``` -### 3. 驱动信息文件 +## 事件回调 -包含系统中所有驱动程序的详细信息: +`OnCrash` 是单次崩溃事件回调,只在检测到 Dump 后触发。它拿到的是整理后的 `CrashInfo`: -```text -Module Name Display Name Description Driver Type Start Mode State Status -============ ====================== ====================== ============= ========== ========== ========== -360AntiAttac 360Safe Anti Attack Se 360Safe Anti Attack Se Kernel System Running OK -360AntiHacke 360Safe Anti Hacker Se 360Safe Anti Hacker Se Kernel System Running OK -// ...更多驱动信息 +```csharp +public readonly record struct CrashInfo +{ + public string DumpFilePath { get; init; } + public string CrashReportPath { get; init; } + public string Version { get; init; } + public int ExitCode { get; init; } +} ``` -### 4. 系统信息文件 +常见用途: -完整的操作系统和硬件配置信息: +| 场景 | 做法 | +| --- | --- | +| 上传诊断包 | 在回调中打包 Dump、JSON 和 Windows 诊断文件,上传到内部日志平台 | +| 提示用户 | 告知“新版本启动失败,已恢复上一版本”,并附带问题编号 | +| 记录业务审计 | 把 `Version`、`ExitCode`、报告路径写入你的业务日志 | + +回调异常会被 Bowl 记录到追踪日志中,不会阻止 `LaunchAsync` 返回最终 `BowlResult`。取消操作请通过 `CancellationToken` 传递。 + +## 日志开关 + +Bowl 使用公开的 `GeneralTracer` 写运行追踪。默认会输出到控制台,并在运行目录下按日期写入: ```text -Host Name: **** -OS Name: Microsoft Windows 11 Pro -OS Version: 10.0.*** Build 22*** -System Manufacturer: ASUS -System Model: System Product Name -Processor(s): Intel** Family * Model *** -Total Physical Memory: 16,194 MB -// ...更多系统信息 +Logs/generalupdate-trace yyyy-MM-dd.log ``` -### 5. 系统事件日志 +如果你的场景对启动性能、磁盘写入或控制台输出非常敏感,可以关闭追踪: -Windows 事件查看器格式的系统日志(.evtx 文件): +```csharp +GeneralTracer.SetTracingEnabled(false); -![系统事件日志](imgs/evtx.png) +var result = await new Bowl().LaunchAsync(context); ---- +GeneralTracer.SetTracingEnabled(true); +``` -## 注意事项与警告 +关闭后,Bowl 自身的诊断追踪会减少,但崩溃 Dump 和失败 JSON 的生成逻辑不依赖该开关。排查升级失败时建议保持开启;稳定生产环境可按你的性能策略关闭。 -### ⚠️ 重要提示 +## 平台差异 -1. **工作模式选择** - - `Upgrade` 模式:专门用于与 GeneralUpdate 框架集成,包含内部逻辑处理 - - `Normal` 模式:可独立使用,适合监控任何 .NET 应用程序 +| 平台 | 监控工具 | 诊断导出 | 注意事项 | +| --- | --- | --- | --- | +| Windows | 内置 ProcDump:`procdump.exe`、`procdump64.exe`、`procdump64a.exe` | 支持 `driverInfo.txt`、`systeminfo.txt`、`systemlog.evtx` | 监控工具路径来自 `TargetPath/Applications/Windows`;需要足够权限生成 Dump | +| Linux | 内置 deb/rpm 包 + `install.sh` 安装 ProcDump 后调用 `procdump` | 当前为 no-op | 支持 Ubuntu、Debian、RHEL、CentOS、Fedora、ClearOS 映射包;脚本可能需要 `sudo` | +| macOS | `/usr/bin/lldb` | 当前为 no-op | 受 SIP、调试权限、签名策略影响;当前是基础实现 | -2. **权限要求** - - Bowl 需要足够的权限来生成 Dump 文件和读取系统信息 - - 建议以管理员权限运行需要监控的应用程序 +NuGet 包会把 `Applications/**/*` 作为内容输出到构建目录。自部署时请确认这些工具文件没有被裁剪,否则平台策略可能返回“监控工具不可用”或进程启动失败。 -3. **磁盘空间** - - Dump 文件可能占用大量磁盘空间(通常 50-200 MB) - - 确保 FailDirectory 所在磁盘有足够的可用空间 +## 恢复场景 -4. **依赖项** - - Bowl 使用 ProcDump 工具生成 Dump 文件,该工具已内置在组件中 - - 无需额外安装依赖项 +假设用户从 `1.0.0` 升级到 `2.0.0`,新版本启动后立即崩溃: -### 💡 最佳实践 +1. 升级流程先把旧版本备份到 `BackupDirectory`,例如 `C:\Program Files\MyApp\2.0.0`。 +2. 新版本文件被复制到 `TargetPath`。 +3. 主程序启动,同时 Bowl 使用 `ProcessNameOrId = "MyApp.exe"` 监控启动期异常。 +4. ProcDump 捕获到未处理异常,写出 `fail\2.0.0\2.0.0_fail.dmp`。 +5. Bowl 写出 `2.0.0_fail.json`,Windows 下继续导出驱动、系统信息和最近系统日志。 +6. 因为 `WorkModel == "Upgrade"` 且 `AutoRestore == true`,Bowl 将 `BackupDirectory` 覆盖复制回 `TargetPath`。 +7. Bowl 写入 `UpgradeFail = "2.0.0"`;Core 下次检测到服务端仍返回 `2.0.0` 或更低版本时,会跳过这个已知失败版本,直到服务端提供更高版本。 +8. `OnCrash` 回调可以上传诊断包,或提示用户已经回退到可用版本。 -- **版本号管理**:为每个版本使用独立的故障目录,便于问题追踪 -- **日志清理**:定期清理旧版本的故障信息,避免磁盘空间耗尽 -- **测试验证**:在生产环境部署前,在测试环境验证监控功能 +这个机制的目标是降低“升级成功但新版本打不开”的风险:用户回到可启动版本,开发者拿到 Dump 和上下文继续修复。 ---- +## 旧 API 迁移 -## 适用平台 +旧示例中的 `GeneralUpdate.Bowl.Strategys.MonitorParameter` 已标记为过时,推荐迁移到 `BowlContext` 和异步入口: -| 产品 | 版本 | -| --------------- | ----------------- | -| .NET | 5, 6, 7, 8, 9, 10 | -| .NET Framework | 4.6.1 | -| .NET Standard | 2.0 | -| .NET Core | 2.0 | -| ASP.NET | Any | +```csharp +var oldParameter = new GeneralUpdate.Bowl.Strategys.MonitorParameter +{ + ProcessNameOrId = "MyApp.exe", + DumpFileName = "2.0.0_fail.dmp", + FailFileName = "2.0.0_fail.json", + TargetPath = installPath, + FailDirectory = Path.Combine(installPath, "fail", "2.0.0"), + BackupDirectory = Path.Combine(installPath, "2.0.0"), + WorkModel = "Upgrade", + ExtendedField = "2.0.0" +}; ---- +BowlContext context = Bowl.MapToContext(oldParameter); +BowlResult result = await new Bowl().LaunchAsync(context); +``` + +如果是新代码,直接创建 `BowlContext`,不要再依赖旧 `MonitorParameter`。 ## 相关资源 -- **示例代码**:[查看 GitHub 示例](https://github.com/GeneralLibrary/GeneralUpdate-Samples/tree/main/src/Bowl) -- **视频教程**:[观看 Bilibili 教程](https://www.bilibili.com/video/BV1c8iyYZE7P) -- **主仓库**:[GeneralUpdate 项目](https://github.com/GeneralLibrary/GeneralUpdate) +- **示例代码**:[GeneralUpdate-Samples / Bowl](https://github.com/GeneralLibrary/GeneralUpdate-Samples/tree/main/src/Bowl) +- **主仓库**:[GeneralUpdate](https://github.com/GeneralLibrary/GeneralUpdate) diff --git a/website/i18n/en/docusaurus-plugin-content-docs/current/doc/GeneralUpdate.Bowl.md b/website/i18n/en/docusaurus-plugin-content-docs/current/doc/GeneralUpdate.Bowl.md index bd13288..bd21765 100644 --- a/website/i18n/en/docusaurus-plugin-content-docs/current/doc/GeneralUpdate.Bowl.md +++ b/website/i18n/en/docusaurus-plugin-content-docs/current/doc/GeneralUpdate.Bowl.md @@ -4,327 +4,301 @@ sidebar_position: 3 # GeneralUpdate.Bowl -## Component Overview +## Overview -**GeneralUpdate.Bowl** is an independent process monitoring component that launches before the end of the upgrade process. It is responsible for starting the main client application and monitoring its running status. This component provides comprehensive crash monitoring and diagnostic capabilities. When the monitored application encounters an exception, it automatically exports Dump files, driver information, system information, and event logs to help developers quickly locate issues. +**GeneralUpdate.Bowl** is the startup guard that runs after an application update. It does not download, unpack, or replace update packages. Instead, it watches the target process when the new files have been installed and the main application is starting. If startup crashes, Bowl captures a dump, writes a failure report, exports diagnostics, and, in upgrade mode, restores the backup directory to the installation directory so users are not left on a broken version. + +**Namespace:** `GeneralUpdate.Bowl` -**Namespace:** `GeneralUpdate.Bowl` **Assembly:** `GeneralUpdate.Bowl.dll` -```csharp -public sealed class Bowl -``` +**Current main entry:** `new Bowl().LaunchAsync(BowlContext context, CancellationToken ct = default)` ---- +## Navigation -## Core Features +| Topic | Use it for | +| --- | --- | +| [Lifecycle placement](#lifecycle-placement) | Where Bowl belongs in the update flow | +| [Quick start](#quick-start) | Start monitoring with the current `BowlContext` API | +| [Crash detection and recovery flow](#crash-detection-and-recovery-flow) | What Bowl does after a crash | +| [BowlContext options](#bowlcontext-options) | Configuration fields and recommended values | +| [Output files](#output-files) | Where dumps, reports, diagnostics, and trace logs are written | +| [Crash callback](#crash-callback) | Upload reports or notify users on crash | +| [Trace logging switch](#trace-logging-switch) | Disable tracing for performance-sensitive scenarios | +| [Platform differences](#platform-differences) | Windows, Linux, and macOS behavior | +| [Recovery scenario](#recovery-scenario) | A practical failed-update rollback example | +| [Migrating from the old API](#migrating-from-the-old-api) | Move from `MonitorParameter` to `BowlContext` | -### 1. Process Monitoring -- Real-time monitoring of target application status -- Automatic detection of process crashes and abnormal exits +## Lifecycle placement -### 2. Crash Diagnostics -- Automatic generation of Dump files (.dmp) for crash analysis -- Export detailed system and driver information -- Collect Windows system event logs +In the full GeneralUpdate flow, Bowl belongs **after file replacement and before users rely on the newly installed version**: -### 3. Version Management -- Store failure information categorized by version number -- Support both upgrade and normal working modes +1. Core obtains update information, downloads packages, validates them, and applies updates. +2. The Core/Upgrade process prepares to start the main application. +3. Bowl starts as guard logic, attaches to the target process, and waits for startup exceptions. +4. If the main application starts normally, no dump is produced and Bowl returns the monitoring result. +5. If the main application crashes during startup, Bowl runs the failure pipeline and restores the backup when configured. ---- +In the current Core code, the Windows `UpdateStrategy` starts the main application after the update and also starts the configured Bowl helper process. The Linux/macOS Core strategies do not provide the same automatic Bowl helper launch, so use your launcher, service script, or a separate process to call `LaunchAsync` explicitly on those platforms. -## Quick Start +:::tip +Bowl is a post-update health check and rollback guard. It is not firmware recovery, OS restore, or an update package installer. Its scope is application startup crash diagnostics and application-directory backup restoration. +::: -### Installation +## Quick start -Install GeneralUpdate.Bowl via NuGet: +### Install ```bash dotnet add package GeneralUpdate.Bowl ``` -### Initialization and Usage +### Upgrade-mode monitoring -The following example demonstrates how to use the Bowl component to monitor an application: +Upgrade mode is intended for an upgrader or Bowl helper process. `BackupDirectory` points to the pre-update backup, `TargetPath` points to the current installation directory, and `ExtendedField` usually stores the version being monitored. ```csharp using GeneralUpdate.Bowl; -using GeneralUpdate.Bowl.Strategys; +var version = "2.0.0"; var installPath = AppDomain.CurrentDomain.BaseDirectory; -var lastVersion = "1.0.0.3"; -var processInfo = new MonitorParameter + +var context = new BowlContext { - ProcessNameOrId = "YourApp.exe", - DumpFileName = $"{lastVersion}_fail.dmp", - FailFileName = $"{lastVersion}_fail.json", + ProcessNameOrId = "MyApp.exe", + DumpFileName = $"{version}_fail.dmp", + FailFileName = $"{version}_fail.json", TargetPath = installPath, - FailDirectory = Path.Combine(installPath, "fail", lastVersion), - BackupDirectory = Path.Combine(installPath, lastVersion), - WorkModel = "Normal" // Use Normal mode for standalone monitoring + FailDirectory = Path.Combine(installPath, "fail", version), + BackupDirectory = Path.Combine(installPath, version), + WorkModel = "Upgrade", + ExtendedField = version, + TimeoutMs = 30_000, + DumpType = DumpType.Full, + AutoRestore = true, + OnCrash = (info, ct) => + { + Console.WriteLine($"Crash dump: {info.DumpFilePath}"); + Console.WriteLine($"Crash report: {info.CrashReportPath}"); + return Task.CompletedTask; + } }; -Bowl.Launch(processInfo); -``` - ---- - -## Core API Reference - -### Launch Method - -Start the process monitoring functionality. - -**Method Signature:** - -```csharp -public static void Launch(MonitorParameter? monitorParameter = null) -``` -**Parameters:** +BowlResult result = await new Bowl().LaunchAsync(context); -#### MonitorParameter Class - -```csharp -public class MonitorParameter -{ - /// - /// Directory being monitored - /// - public string TargetPath { get; set; } - - /// - /// Directory where captured exception information is exported - /// - public string FailDirectory { get; set; } - - /// - /// Backup directory - /// - public string BackupDirectory { get; set; } - - /// - /// Name or ID of the process being monitored - /// - public string ProcessNameOrId { get; set; } - - /// - /// Dump file name - /// - public string DumpFileName { get; set; } - - /// - /// Upgrade package version information (.json) file name - /// - public string FailFileName { get; set; } - - /// - /// Work Mode: - /// - Upgrade: Upgrade mode, primarily used in conjunction with GeneralUpdate for internal logic handling. - /// Do not modify arbitrarily when the default mode is activated. - /// - Normal: Normal mode, can be used independently to monitor a single program. - /// Exports crash information when the program crashes. - /// - public string WorkModel { get; set; } = "Upgrade"; +if (result.DumpCaptured && result.Restored) +{ + Console.WriteLine("The upgraded version crashed and the backup was restored."); } ``` ---- - -## Practical Usage Examples +### Standalone monitoring -### Example 1: Standalone Mode Application Monitoring +`Normal` mode only captures crash artifacts and invokes callbacks. It does not restore backups and does not write the `UpgradeFail` failed-version marker. ```csharp -using GeneralUpdate.Bowl; -using GeneralUpdate.Bowl.Strategys; - -// Configure monitoring parameters -var installPath = AppDomain.CurrentDomain.BaseDirectory; -var currentVersion = "1.0.0.5"; - -var monitorConfig = new MonitorParameter +var context = new BowlContext { - ProcessNameOrId = "MyApplication.exe", - DumpFileName = $"{currentVersion}_crash.dmp", - FailFileName = $"{currentVersion}_crash.json", - TargetPath = installPath, - FailDirectory = Path.Combine(installPath, "crash_reports", currentVersion), - BackupDirectory = Path.Combine(installPath, "backups", currentVersion), - WorkModel = "Normal" // Standalone monitoring mode + ProcessNameOrId = "MyWorker.exe", + DumpFileName = "startup_fail.dmp", + FailFileName = "startup_fail.json", + TargetPath = AppDomain.CurrentDomain.BaseDirectory, + FailDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fail", "startup"), + BackupDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "backup"), + WorkModel = "Normal", + TimeoutMs = 15_000, + DumpType = DumpType.Mini, + AutoRestore = false }; -// Start monitoring -Bowl.Launch(monitorConfig); +BowlResult result = await new Bowl().LaunchAsync(context); ``` -### Example 2: Use with GeneralUpdate - -```csharp -using GeneralUpdate.Bowl; -using GeneralUpdate.Bowl.Strategys; - -// Start Bowl monitoring after upgrade completion -var installPath = AppDomain.CurrentDomain.BaseDirectory; -var upgradedVersion = "2.0.0.1"; +## Crash detection and recovery flow -var upgradeMonitor = new MonitorParameter -{ - ProcessNameOrId = "UpdatedApp.exe", - DumpFileName = $"{upgradedVersion}_fail.dmp", - FailFileName = $"{upgradedVersion}_fail.json", - TargetPath = installPath, - FailDirectory = Path.Combine(installPath, "fail", upgradedVersion), - BackupDirectory = Path.Combine(installPath, upgradedVersion), - WorkModel = "Upgrade" // Upgrade mode -}; +`LaunchAsync` uses a simple signal: the platform strategy starts the monitoring tool and writes to `FailDirectory`; Bowl then checks whether `{FailDirectory}/{DumpFileName}` exists. If the dump file exists, startup is treated as failed. -Bowl.Launch(upgradeMonitor); -``` +| Stage | Current implementation | +| --- | --- | +| Prepare monitoring | Selects `WindowsBowlStrategy`, `LinuxBowlStrategy`, or `MacBowlStrategy` based on the OS | +| Capture exception | Windows uses ProcDump; Linux tries to install and call ProcDump; macOS uses basic `lldb` support | +| Detect crash | Checks for the configured dump file in `FailDirectory` | +| Generate report | Writes `{version}_fail.json` with monitoring parameters and tool output | +| Export diagnostics | On Windows, runs `Applications/Windows/export.bat` for driver info, system info, and recent system logs | +| Restore backup | Only when `WorkModel == "Upgrade"` and `AutoRestore == true`, copies `BackupDirectory` back over `TargetPath` | +| Mark failed version | In upgrade mode, writes `UpgradeFail = ExtendedField`; Core later skips updates at or below that failed version | +| Notify application | If `OnCrash` is configured, passes dump path, report path, version, and exit code | ---- +`TimeoutMs` is the monitoring child process timeout. If the timeout expires and no dump exists, Bowl does not run the recovery pipeline. In integrations, treat `DumpCaptured` as the primary crash signal instead of relying only on `Success`. -## Crash Information Capture +## BowlContext options -When a crash is detected, the following files will be generated in the running directory: +| Option | Meaning | Recommendation | +| --- | --- | --- | +| `ProcessNameOrId` | Target process name or PID | Process name works on Windows; PID is preferred on Linux | +| `DumpFileName` | Dump file name | Include the version, for example `2.0.0_fail.dmp` | +| `FailFileName` | Crash report JSON file name | Match the dump version, for example `2.0.0_fail.json` | +| `TargetPath` | Current application installation root | Backup restoration copies files back here | +| `FailDirectory` | Failure artifact output directory | Use `Path.Combine(TargetPath, "fail", version)` | +| `BackupDirectory` | Pre-update backup directory | Must exist and be complete when `AutoRestore` is enabled | +| `WorkModel` | `Upgrade` or `Normal` | Use `Upgrade` for post-update rollback; use `Normal` for standalone crash capture | +| `ExtendedField` | Extension field, currently used mainly as version | Written to `UpgradeFail` in upgrade mode | +| `TimeoutMs` | Monitoring child process timeout | Normalizes to 30000 ms by default; increase for slow-starting apps | +| `DumpType` | `Full`, `Mini`, or `Heap` | Use `Mini` for smaller production artifacts; use `Full` for hard issues | +| `AutoRestore` | Whether to restore backups automatically | Set explicitly to `true` for upgrade rollback | +| `OnCrash` | Single crash callback | Use it to upload reports, notify users, or write business logs | -- 📒 **Dump file** (`x.0.0.*_fail.dmp`) -- 📒 **Upgrade package version information** (`x.0.0.*_fail.json`) -- 📒 **Driver information** (`driverInfo.txt`) -- 📒 **Operating system/hardware information** (`systeminfo.txt`) -- 📒 **System event log** (`systemlog.evtx`) +### Choosing DumpType -These files will be exported to the "fail" directory, categorized by version number. +| Type | Windows ProcDump flag | Characteristics | +| --- | --- | --- | +| `Full` | `-ma` | Most complete data, largest file, best for hard-to-reproduce issues | +| `Mini` | `-mm` | Smaller and faster, a good production default | +| `Heap` | `-mh` | Mini dump with heap information; between Mini and Full | -![Crash Files](imgs/crash.jpg) +## Output files -### 1. Dump File +For failed upgrades, store artifacts by version: -The Dump file contains a memory snapshot at the moment of crash, which can be used for debugging analysis: +```text +MyApp/ + fail/ + 2.0.0/ + 2.0.0_fail.dmp + 2.0.0_fail.json + driverInfo.txt + systeminfo.txt + systemlog.evtx + Logs/ + generalupdate-trace 2026-01-01.log +``` -![Dump File](imgs/dump.png) +| File | Source | Contents | +| --- | --- | --- | +| `{version}_fail.dmp` | ProcDump or lldb | Memory snapshot from the crash | +| `{version}_fail.json` | `CrashReporter` | Mapped `BowlContext` parameters and monitoring tool output lines | +| `driverInfo.txt` | Windows `driverquery` | Windows driver list | +| `systeminfo.txt` | Windows `systeminfo` | OS, hardware, memory, and related system information | +| `systemlog.evtx` | Windows `wevtutil` | Windows System event log for the last day | +| `Logs/generalupdate-trace yyyy-MM-dd.log` | `GeneralTracer` | Bowl runtime trace log | -### 2. Version Information File +Non-Windows platforms currently do not export `driverInfo.txt`, `systeminfo.txt`, or `systemlog.evtx`, but Bowl still attempts to produce the dump and failure JSON. -Detailed crash report in JSON format, including parameter configuration and ProcDump output: +The failure JSON is generated by the current `CrashReporter`: ```json { -"Parameter": { -"TargetPath": "D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\", -"FailDirectory": "D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\fail\\1.0.0.3", -"BackupDirectory": "D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\1.0.0.3", -"ProcessNameOrId": "JsonTest.exe", -"DumpFileName": "1.0.0.3_fail.dmp", -"FailFileName": "1.0.0.3_fail.json", -"WorkModel": "Normal", -"ExtendedField": null -}, -"ProcdumpOutPutLines": [ - "ProcDump v11.0 - Sysinternals process dump utility", - "Copyright (C) 2009-2022 Mark Russinovich and Andrew Richards", - "Sysinternals - www.sysinternals.com", - "Process: JsonTest.exe (19712)", - "Process image: D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\JsonTest.exe", "CPU threshold: n/a", - "Performance counter: n/a", "Commit threshold: n/a", - "Threshold seconds: n/a", "Hung window check: Disabled", "Log debug strings: Disabled", - "Exception monitor: Unhandled", "Exception filter: [Includes]", - " *", - " [Excludes]", - "Terminate monitor: Disabled", - "Cloning type: Disabled", - "Concurrent limit: n/a", - "Avoid outage: n/a", - "Number of dumps: 1", - "Dump folder: D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\fail\\1.0.0.3\\", - "Dump filename/mask: 1.0.0.3_fail", - "Queue to WER: Disabled", "Kill after dump: Disabled", - "Press Ctrl-C to end monitoring without terminating the process.", - "[19:05:23] Exception: E0434352.CLR", "[19:05:23] Unhandled: E0434352.CLR", - "[19:05:23] Dump 1 initiated: D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\fail\\1.0.0.3\\1.0.0.3_fail.dmp", - "[19:05:23] Dump 1 writing: Estimated dump file size is 62 MB.", - "[19:05:23] Dump 1 complete: 62 MB written in 0.1 seconds", - "[19:05:23] Dump count reached."] + "Parameter": { + "TargetPath": "C:\\Program Files\\MyApp", + "FailDirectory": "C:\\Program Files\\MyApp\\fail\\2.0.0", + "BackupDirectory": "C:\\Program Files\\MyApp\\2.0.0", + "ProcessNameOrId": "MyApp.exe", + "DumpFileName": "2.0.0_fail.dmp", + "FailFileName": "2.0.0_fail.json", + "WorkModel": "Upgrade", + "ExtendedField": "2.0.0" + }, + "ProcdumpOutPutLines": [ + "ProcDump v11.0 - Sysinternals process dump utility", + "[10:00:03] Dump 1 initiated: C:\\Program Files\\MyApp\\fail\\2.0.0\\2.0.0_fail.dmp", + "[10:00:03] Dump count reached." + ] } ``` -### 3. Driver Information File +## Crash callback -Contains detailed information about all drivers in the system: +`OnCrash` is a single crash callback. It fires only after Bowl detects a dump and receives a `CrashInfo` payload: -```text -Module Name Display Name Description Driver Type Start Mode State Status -============ ====================== ====================== ============= ========== ========== ========== -360AntiAttac 360Safe Anti Attack Se 360Safe Anti Attack Se Kernel System Running OK -360AntiHacke 360Safe Anti Hacker Se 360Safe Anti Hacker Se Kernel System Running OK -// ...more driver information +```csharp +public readonly record struct CrashInfo +{ + public string DumpFilePath { get; init; } + public string CrashReportPath { get; init; } + public string Version { get; init; } + public int ExitCode { get; init; } +} ``` -### 4. System Information File +Common uses: -Complete operating system and hardware configuration information: +| Scenario | Approach | +| --- | --- | +| Upload diagnostics | Package the dump, JSON report, and Windows diagnostics, then upload them to your internal log platform | +| Notify users | Tell the user the new version failed to start and the previous version was restored | +| Audit business events | Record `Version`, `ExitCode`, and report paths in your own log system | + +Callback exceptions are written to the trace log and do not stop `LaunchAsync` from returning its final `BowlResult`. Use the `CancellationToken` for cancellation. + +## Trace logging switch + +Bowl uses the public `GeneralTracer` for runtime tracing. By default it writes to the console and creates a daily file under the runtime directory: ```text -Host Name: **** -OS Name: Microsoft Windows 11 Pro -OS Version: 10.0.*** Build 22*** -System Manufacturer: ASUS -System Model: System Product Name -Processor(s): Intel** Family * Model *** -Total Physical Memory: 16,194 MB -// ...more system information +Logs/generalupdate-trace yyyy-MM-dd.log ``` -### 5. System Event Log +For startup-performance, disk-write, or console-output sensitive scenarios, disable tracing: -System log in Windows Event Viewer format (.evtx file): +```csharp +GeneralTracer.SetTracingEnabled(false); -![System Event Log](imgs/evtx.png) +var result = await new Bowl().LaunchAsync(context); ---- +GeneralTracer.SetTracingEnabled(true); +``` -## Notes and Warnings +Disabling tracing reduces Bowl's own diagnostic logs, but dump and failure JSON generation do not depend on this switch. Keep tracing enabled while investigating update failures; disable it in stable production paths according to your performance policy. -### ⚠️ Important Notes +## Platform differences -1. **Work Mode Selection** - - `Upgrade` mode: Specifically for integration with GeneralUpdate framework, includes internal logic processing - - `Normal` mode: Can be used independently, suitable for monitoring any .NET application +| Platform | Monitoring tool | Diagnostic export | Notes | +| --- | --- | --- | --- | +| Windows | Bundled ProcDump: `procdump.exe`, `procdump64.exe`, `procdump64a.exe` | Supports `driverInfo.txt`, `systeminfo.txt`, `systemlog.evtx` | Tool path comes from `TargetPath/Applications/Windows`; sufficient dump permissions are required | +| Linux | Bundled deb/rpm packages + `install.sh`, then `procdump` | Currently no-op | Package mapping covers Ubuntu, Debian, RHEL, CentOS, Fedora, and ClearOS; the script may require `sudo` | +| macOS | `/usr/bin/lldb` | Currently no-op | Affected by SIP, debugging permission, and signing policy; current support is basic | -2. **Permission Requirements** - - Bowl requires sufficient permissions to generate Dump files and read system information - - It is recommended to run the monitored application with administrator privileges +The NuGet package outputs `Applications/**/*` as content. If you self-deploy, make sure these files are not trimmed, otherwise the platform strategy may report that monitoring tooling is unavailable or fail to start the tool process. -3. **Disk Space** - - Dump files may consume significant disk space (typically 50-200 MB) - - Ensure sufficient available space on the disk where FailDirectory is located +## Recovery scenario -4. **Dependencies** - - Bowl uses the ProcDump tool to generate Dump files, which is built into the component - - No additional dependencies need to be installed +Suppose a user upgrades from `1.0.0` to `2.0.0` and the new version crashes immediately: -### 💡 Best Practices +1. The update flow first stores the previous version in `BackupDirectory`, for example `C:\Program Files\MyApp\2.0.0`. +2. The new version is copied into `TargetPath`. +3. The main application starts, while Bowl monitors startup with `ProcessNameOrId = "MyApp.exe"`. +4. ProcDump captures the unhandled exception and writes `fail\2.0.0\2.0.0_fail.dmp`. +5. Bowl writes `2.0.0_fail.json`; on Windows it also exports driver info, system info, and recent system logs. +6. Because `WorkModel == "Upgrade"` and `AutoRestore == true`, Bowl copies `BackupDirectory` back over `TargetPath`. +7. Bowl writes `UpgradeFail = "2.0.0"`; the next Core check skips this known-failed version while the server still returns `2.0.0` or lower, until a higher version is available. +8. `OnCrash` can upload the diagnostic package or tell the user that the app has been restored to a working version. -- **Version Management**: Use separate failure directories for each version for easier issue tracking -- **Log Cleanup**: Regularly clean up failure information from old versions to avoid disk space exhaustion -- **Testing**: Verify monitoring functionality in a test environment before production deployment +The goal is to reduce the risk of "the update succeeded but the new app cannot start": users return to a runnable version, and developers get the dump plus context needed to fix the issue. ---- +## Migrating from the old API -## Applicable Platforms +The old `GeneralUpdate.Bowl.Strategys.MonitorParameter` type is obsolete. Prefer `BowlContext` and the async entry point: -| Product | Version | -| --------------- | ----------------- | -| .NET | 5, 6, 7, 8, 9, 10 | -| .NET Framework | 4.6.1 | -| .NET Standard | 2.0 | -| .NET Core | 2.0 | -| ASP.NET | Any | +```csharp +var oldParameter = new GeneralUpdate.Bowl.Strategys.MonitorParameter +{ + ProcessNameOrId = "MyApp.exe", + DumpFileName = "2.0.0_fail.dmp", + FailFileName = "2.0.0_fail.json", + TargetPath = installPath, + FailDirectory = Path.Combine(installPath, "fail", "2.0.0"), + BackupDirectory = Path.Combine(installPath, "2.0.0"), + WorkModel = "Upgrade", + ExtendedField = "2.0.0" +}; ---- +BowlContext context = Bowl.MapToContext(oldParameter); +BowlResult result = await new Bowl().LaunchAsync(context); +``` + +For new code, create `BowlContext` directly instead of depending on `MonitorParameter`. -## Related Resources +## Related resources -- **Example Code**: [View GitHub Examples](https://github.com/GeneralLibrary/GeneralUpdate-Samples/tree/main/src/Bowl) -- **Video Tutorial**: [Watch Bilibili Tutorial](https://www.bilibili.com/video/BV1c8iyYZE7P) -- **Main Repository**: [GeneralUpdate Project](https://github.com/GeneralLibrary/GeneralUpdate) +- **Samples:** [GeneralUpdate-Samples / Bowl](https://github.com/GeneralLibrary/GeneralUpdate-Samples/tree/main/src/Bowl) +- **Main repository:** [GeneralUpdate](https://github.com/GeneralLibrary/GeneralUpdate) diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/doc/GeneralUpdate.Bowl.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/doc/GeneralUpdate.Bowl.md index 44e0b4f..4ecc369 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/doc/GeneralUpdate.Bowl.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/doc/GeneralUpdate.Bowl.md @@ -4,325 +4,301 @@ sidebar_position: 3 # GeneralUpdate.Bowl -## 组件概览 +## 简介 -**GeneralUpdate.Bowl** 是一个独立的进程监控组件,在升级流程结束前启动,负责启动主客户端应用程序并监控其运行状态。该组件提供了完整的崩溃监控和诊断能力,当被监控的应用程序发生异常时,会自动导出Dump文件、驱动信息、系统信息和事件日志,帮助开发者快速定位问题。 +**GeneralUpdate.Bowl** 是升级完成后的启动守护组件。它不负责下载、解压或替换升级包,而是在新版本文件落地、主程序即将启动或已经启动时,监控目标进程是否在启动阶段崩溃。如果捕获到崩溃,它会生成 Dump、写出失败报告、导出诊断信息,并在升级模式下把备份目录恢复回安装目录,避免用户一直停留在不可启动的新版本上。 + +**命名空间:** `GeneralUpdate.Bowl` -**命名空间:** `GeneralUpdate.Bowl` **程序集:** `GeneralUpdate.Bowl.dll` -```csharp -public sealed class Bowl -``` +**当前主要入口:** `new Bowl().LaunchAsync(BowlContext context, CancellationToken ct = default)` ---- +## 阅读导航 -## 核心特性 +| 主题 | 适合解决的问题 | +| --- | --- | +| [生命周期位置](#生命周期位置) | Bowl 应该在升级流程的哪个阶段运行 | +| [快速接入](#快速接入) | 用当前 `BowlContext` API 完成一次监控 | +| [崩溃检测与恢复流程](#崩溃检测与恢复流程) | 崩溃后组件具体做了什么 | +| [BowlContext 参数](#bowlcontext-参数) | 每个配置项的含义和推荐值 | +| [输出文件](#输出文件) | Dump、失败报告、系统诊断、追踪日志在哪里 | +| [事件回调](#事件回调) | 如何在崩溃时上传报告或通知用户 | +| [日志开关](#日志开关) | 如何为了性能关闭组件追踪日志 | +| [平台差异](#平台差异) | Windows、Linux、macOS 的监控能力差异 | +| [恢复场景](#恢复场景) | 一次真实升级失败回滚过程 | +| [旧 API 迁移](#旧-api-迁移) | 从 `MonitorParameter` 迁移到 `BowlContext` | -### 1. 进程监控 -- 实时监控目标应用程序的运行状态 -- 自动检测进程崩溃和异常退出 +## 生命周期位置 -### 2. 崩溃诊断 -- 自动生成Dump文件(.dmp)用于崩溃分析 -- 导出详细的系统和驱动信息 -- 收集Windows系统事件日志 +在 GeneralUpdate 的完整升级链路中,Bowl 位于**文件替换完成之后、用户正式使用新版本之前**: -### 3. 版本化管理 -- 按版本号分类存储故障信息 -- 支持升级和正常两种工作模式 +1. Core 获取更新信息、下载包、校验并应用更新。 +2. Core/Upgrade 进程准备启动主程序。 +3. Bowl 作为守护逻辑启动,附加到目标进程并等待启动期异常。 +4. 主程序正常启动:没有 Dump 产生,Bowl 返回本次监控结果。 +5. 主程序启动崩溃:Bowl 进入故障处理管线,生成诊断文件并按配置恢复备份。 ---- +在当前 Core 代码中,Windows 的 `UpdateStrategy` 会在更新完成后通过 OS 策略启动主程序,并在配置了 Bowl 进程名时一并启动 Bowl 辅助进程。Linux/macOS 侧 Core 策略没有同等的 Bowl helper 自动启动能力,通常需要由你的启动器、服务脚本或独立进程显式调用 `LaunchAsync`。 -## 快速开始 +:::tip +Bowl 是“升级后健康检查与回滚保护”,不是固件恢复、系统还原或升级包安装器。它处理的是应用启动崩溃后的诊断与应用目录级备份恢复。 +::: -### 安装 +## 快速接入 -通过 NuGet 安装 GeneralUpdate.Bowl: +### 安装 ```bash dotnet add package GeneralUpdate.Bowl ``` -### 初始化与使用 +### 升级模式监控 -以下示例展示了如何使用 Bowl 组件监控应用程序: +升级模式适合放在升级程序或 Bowl helper 中运行。关键点是:`BackupDirectory` 指向升级前保留的备份,`TargetPath` 指向当前安装目录,`ExtendedField` 填本次升级版本号。 ```csharp using GeneralUpdate.Bowl; -using GeneralUpdate.Bowl.Strategys; +var version = "2.0.0"; var installPath = AppDomain.CurrentDomain.BaseDirectory; -var lastVersion = "1.0.0.3"; -var processInfo = new MonitorParameter + +var context = new BowlContext { - ProcessNameOrId = "YourApp.exe", - DumpFileName = $"{lastVersion}_fail.dmp", - FailFileName = $"{lastVersion}_fail.json", + ProcessNameOrId = "MyApp.exe", + DumpFileName = $"{version}_fail.dmp", + FailFileName = $"{version}_fail.json", TargetPath = installPath, - FailDirectory = Path.Combine(installPath, "fail", lastVersion), - BackupDirectory = Path.Combine(installPath, lastVersion), - WorkModel = "Normal" // 使用 Normal 模式独立监控 + FailDirectory = Path.Combine(installPath, "fail", version), + BackupDirectory = Path.Combine(installPath, version), + WorkModel = "Upgrade", + ExtendedField = version, + TimeoutMs = 30_000, + DumpType = DumpType.Full, + AutoRestore = true, + OnCrash = (info, ct) => + { + Console.WriteLine($"Crash dump: {info.DumpFilePath}"); + Console.WriteLine($"Crash report: {info.CrashReportPath}"); + return Task.CompletedTask; + } }; -Bowl.Launch(processInfo); -``` - ---- - -## 核心 API 参考 -### Launch 方法 +BowlResult result = await new Bowl().LaunchAsync(context); -启动进程监控功能。 - -**方法签名:** - -```csharp -public static void Launch(MonitorParameter? monitorParameter = null) -``` - -**参数:** - -#### MonitorParameter 类 - -```csharp -public class MonitorParameter -{ - /// - /// 被监控的目录 - /// - public string TargetPath { get; set; } - - /// - /// 导出异常信息的目录 - /// - public string FailDirectory { get; set; } - - /// - /// 备份目录 - /// - public string BackupDirectory { get; set; } - - /// - /// 被监控进程的名称或ID - /// - public string ProcessNameOrId { get; set; } - - /// - /// Dump 文件名 - /// - public string DumpFileName { get; set; } - - /// - /// 升级包版本信息(.json)文件名 - /// - public string FailFileName { get; set; } - - /// - /// 工作模式: - /// - Upgrade: 升级模式,主要用于与 GeneralUpdate 配合使用,内部逻辑处理,默认模式启动时请勿随意修改 - /// - Normal: 正常模式,可独立使用监控单个程序,程序崩溃时导出崩溃信息 - /// - public string WorkModel { get; set; } = "Upgrade"; +if (result.DumpCaptured && result.Restored) +{ + Console.WriteLine("The upgraded version crashed and the backup was restored."); } ``` ---- - -## 实际使用示例 +### 独立监控模式 -### 示例 1:独立模式监控应用 +`Normal` 模式只做崩溃捕获、报告输出和回调通知,不会自动恢复备份,也不会写入 `UpgradeFail` 失败版本标记。 ```csharp -using GeneralUpdate.Bowl; -using GeneralUpdate.Bowl.Strategys; - -// 配置监控参数 -var installPath = AppDomain.CurrentDomain.BaseDirectory; -var currentVersion = "1.0.0.5"; - -var monitorConfig = new MonitorParameter +var context = new BowlContext { - ProcessNameOrId = "MyApplication.exe", - DumpFileName = $"{currentVersion}_crash.dmp", - FailFileName = $"{currentVersion}_crash.json", - TargetPath = installPath, - FailDirectory = Path.Combine(installPath, "crash_reports", currentVersion), - BackupDirectory = Path.Combine(installPath, "backups", currentVersion), - WorkModel = "Normal" // 独立监控模式 + ProcessNameOrId = "MyWorker.exe", + DumpFileName = "startup_fail.dmp", + FailFileName = "startup_fail.json", + TargetPath = AppDomain.CurrentDomain.BaseDirectory, + FailDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fail", "startup"), + BackupDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "backup"), + WorkModel = "Normal", + TimeoutMs = 15_000, + DumpType = DumpType.Mini, + AutoRestore = false }; -// 启动监控 -Bowl.Launch(monitorConfig); +BowlResult result = await new Bowl().LaunchAsync(context); ``` -### 示例 2:结合 GeneralUpdate 使用 - -```csharp -using GeneralUpdate.Bowl; -using GeneralUpdate.Bowl.Strategys; +## 崩溃检测与恢复流程 -// 在升级完成后启动 Bowl 监控 -var installPath = AppDomain.CurrentDomain.BaseDirectory; -var upgradedVersion = "2.0.0.1"; +`LaunchAsync` 的核心判断非常直接:平台策略先启动监控工具,监控工具输出到 `FailDirectory`;Bowl 再检查 `{FailDirectory}/{DumpFileName}` 是否存在。存在 Dump 就认为启动阶段发生了崩溃。 -var upgradeMonitor = new MonitorParameter -{ - ProcessNameOrId = "UpdatedApp.exe", - DumpFileName = $"{upgradedVersion}_fail.dmp", - FailFileName = $"{upgradedVersion}_fail.json", - TargetPath = installPath, - FailDirectory = Path.Combine(installPath, "fail", upgradedVersion), - BackupDirectory = Path.Combine(installPath, upgradedVersion), - WorkModel = "Upgrade" // 升级模式 -}; +| 阶段 | 当前实现 | +| --- | --- | +| 准备监控 | 根据操作系统选择 `WindowsBowlStrategy`、`LinuxBowlStrategy` 或 `MacBowlStrategy` | +| 捕获异常 | Windows 使用 ProcDump;Linux 尝试安装并调用 ProcDump;macOS 使用 `lldb` 基础能力 | +| 判断崩溃 | 检查 `FailDirectory` 中是否生成指定 Dump 文件 | +| 生成报告 | 写出 `{version}_fail.json`,包含监控参数和监控工具输出 | +| 导出诊断 | Windows 调用 `Applications/Windows/export.bat` 导出驱动、系统信息和最近系统日志 | +| 恢复备份 | 仅当 `WorkModel == "Upgrade"` 且 `AutoRestore == true` 时,把 `BackupDirectory` 覆盖复制回 `TargetPath` | +| 标记失败版本 | 升级模式下写入 `UpgradeFail = ExtendedField`,Core 后续会跳过小于等于该失败版本的更新 | +| 通知业务 | 如果配置了 `OnCrash`,传出 Dump 路径、报告路径、版本号和退出码 | -Bowl.Launch(upgradeMonitor); -``` +`TimeoutMs` 是监控子进程的等待上限。超时且没有 Dump 时,Bowl 不会执行恢复管线;此时更应该关注 `DumpCaptured` 是否为 `true`,而不是只看 `Success`。 ---- +## BowlContext 参数 -## 崩溃信息捕获 +| 参数 | 说明 | 建议 | +| --- | --- | --- | +| `ProcessNameOrId` | 要监控的进程名或 PID | Windows 可使用进程名;Linux 上更建议传 PID | +| `DumpFileName` | Dump 文件名 | 推荐包含版本号,例如 `2.0.0_fail.dmp` | +| `FailFileName` | 崩溃报告 JSON 文件名 | 推荐和 Dump 同版本,例如 `2.0.0_fail.json` | +| `TargetPath` | 当前应用安装根目录 | 恢复备份时会覆盖复制到这里 | +| `FailDirectory` | 故障文件输出目录 | 推荐 `Path.Combine(TargetPath, "fail", version)` | +| `BackupDirectory` | 升级前备份目录 | `AutoRestore` 打开时必须确保目录存在且内容完整 | +| `WorkModel` | `Upgrade` 或 `Normal` | 升级后回滚用 `Upgrade`;普通崩溃采集用 `Normal` | +| `ExtendedField` | 扩展字段,当前主要存版本号 | 升级模式下会写入 `UpgradeFail` | +| `TimeoutMs` | 监控子进程超时时间 | 默认归一化为 30000 ms,按应用启动耗时调大 | +| `DumpType` | `Full`、`Mini`、`Heap` | 生产环境可先用 `Mini` 降低体积;疑难问题用 `Full` | +| `AutoRestore` | 是否自动恢复备份 | 升级模式要显式设置为 `true` | +| `OnCrash` | 单次崩溃回调 | 适合上传报告、通知用户、写入业务日志 | -当检测到崩溃时,以下文件将在运行目录中生成: +### DumpType 选择 -- 📒 **Dump 文件** (`x.0.0.*_fail.dmp`) -- 📒 **升级包版本信息** (`x.0.0.*_fail.json`) -- 📒 **驱动信息** (`driverInfo.txt`) -- 📒 **操作系统/硬件信息** (`systeminfo.txt`) -- 📒 **系统事件日志** (`systemlog.evtx`) +| 类型 | Windows ProcDump 参数 | 特点 | +| --- | --- | --- | +| `Full` | `-ma` | 信息最完整,文件最大,适合难复现问题 | +| `Mini` | `-mm` | 文件更小,生成更快,适合生产默认采集 | +| `Heap` | `-mh` | 带堆信息的小型 Dump,介于 Mini 和 Full 之间 | -这些文件将按版本号分类导出到 "fail" 目录中。 +## 输出文件 -![崩溃文件](imgs/crash.jpg) +一次升级失败后,推荐按版本存放所有故障文件: -### 1. Dump 文件 - -Dump 文件包含崩溃时刻的内存快照,可用于调试分析: +```text +MyApp/ + fail/ + 2.0.0/ + 2.0.0_fail.dmp + 2.0.0_fail.json + driverInfo.txt + systeminfo.txt + systemlog.evtx + Logs/ + generalupdate-trace 2026-01-01.log +``` -![Dump文件](imgs/dump.png) +| 文件 | 来源 | 内容 | +| --- | --- | --- | +| `{version}_fail.dmp` | ProcDump 或 lldb | 崩溃现场内存快照 | +| `{version}_fail.json` | `CrashReporter` | `BowlContext` 映射参数和监控工具输出行 | +| `driverInfo.txt` | Windows `driverquery` | Windows 驱动列表 | +| `systeminfo.txt` | Windows `systeminfo` | OS、硬件、内存等系统信息 | +| `systemlog.evtx` | Windows `wevtutil` | 最近一天 Windows System 事件日志 | +| `Logs/generalupdate-trace yyyy-MM-dd.log` | `GeneralTracer` | Bowl 自身运行追踪日志 | -### 2. 版本信息文件 +非 Windows 平台当前不会导出 `driverInfo.txt`、`systeminfo.txt`、`systemlog.evtx`,但仍会尽量生成 Dump 和失败 JSON。 -JSON 格式的详细崩溃报告,包含参数配置和 ProcDump 输出: +失败 JSON 的结构来自当前 `CrashReporter`: ```json { -"Parameter": { -"TargetPath": "D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\", -"FailDirectory": "D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\fail\\1.0.0.3", -"BackupDirectory": "D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\1.0.0.3", -"ProcessNameOrId": "JsonTest.exe", -"DumpFileName": "1.0.0.3_fail.dmp", -"FailFileName": "1.0.0.3_fail.json", -"WorkModel": "Normal", -"ExtendedField": null -}, -"ProcdumpOutPutLines": [ - "ProcDump v11.0 - Sysinternals process dump utility", - "Copyright (C) 2009-2022 Mark Russinovich and Andrew Richards", - "Sysinternals - www.sysinternals.com", - "Process: JsonTest.exe (19712)", - "Process image: D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\JsonTest.exe", "CPU threshold: n/a", - "Performance counter: n/a", "Commit threshold: n/a", - "Threshold seconds: n/a", "Hung window check: Disabled", "Log debug strings: Disabled", - "Exception monitor: Unhandled", "Exception filter: [Includes]", - " *", - " [Excludes]", - "Terminate monitor: Disabled", - "Cloning type: Disabled", - "Concurrent limit: n/a", - "Avoid outage: n/a", - "Number of dumps: 1", - "Dump folder: D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\fail\\1.0.0.3\\", - "Dump filename/mask: 1.0.0.3_fail", - "Queue to WER: Disabled", "Kill after dump: Disabled", - "Press Ctrl-C to end monitoring without terminating the process.", - "[19:05:23] Exception: E0434352.CLR", "[19:05:23] Unhandled: E0434352.CLR", - "[19:05:23] Dump 1 initiated: D:\\github_project\\GeneralUpdate\\src\\c#\\Generalupdate.CatBowl\\bin\\Debug\\net9.0\\fail\\1.0.0.3\\1.0.0.3_fail.dmp", - "[19:05:23] Dump 1 writing: Estimated dump file size is 62 MB.", - "[19:05:23] Dump 1 complete: 62 MB written in 0.1 seconds", - "[19:05:23] Dump count reached."] + "Parameter": { + "TargetPath": "C:\\Program Files\\MyApp", + "FailDirectory": "C:\\Program Files\\MyApp\\fail\\2.0.0", + "BackupDirectory": "C:\\Program Files\\MyApp\\2.0.0", + "ProcessNameOrId": "MyApp.exe", + "DumpFileName": "2.0.0_fail.dmp", + "FailFileName": "2.0.0_fail.json", + "WorkModel": "Upgrade", + "ExtendedField": "2.0.0" + }, + "ProcdumpOutPutLines": [ + "ProcDump v11.0 - Sysinternals process dump utility", + "[10:00:03] Dump 1 initiated: C:\\Program Files\\MyApp\\fail\\2.0.0\\2.0.0_fail.dmp", + "[10:00:03] Dump count reached." + ] } ``` -### 3. 驱动信息文件 +## 事件回调 -包含系统中所有驱动程序的详细信息: +`OnCrash` 是单次崩溃事件回调,只在检测到 Dump 后触发。它拿到的是整理后的 `CrashInfo`: -```text -Module Name Display Name Description Driver Type Start Mode State Status -============ ====================== ====================== ============= ========== ========== ========== -360AntiAttac 360Safe Anti Attack Se 360Safe Anti Attack Se Kernel System Running OK -360AntiHacke 360Safe Anti Hacker Se 360Safe Anti Hacker Se Kernel System Running OK -// ...更多驱动信息 +```csharp +public readonly record struct CrashInfo +{ + public string DumpFilePath { get; init; } + public string CrashReportPath { get; init; } + public string Version { get; init; } + public int ExitCode { get; init; } +} ``` -### 4. 系统信息文件 +常见用途: -完整的操作系统和硬件配置信息: +| 场景 | 做法 | +| --- | --- | +| 上传诊断包 | 在回调中打包 Dump、JSON 和 Windows 诊断文件,上传到内部日志平台 | +| 提示用户 | 告知“新版本启动失败,已恢复上一版本”,并附带问题编号 | +| 记录业务审计 | 把 `Version`、`ExitCode`、报告路径写入你的业务日志 | + +回调异常会被 Bowl 记录到追踪日志中,不会阻止 `LaunchAsync` 返回最终 `BowlResult`。取消操作请通过 `CancellationToken` 传递。 + +## 日志开关 + +Bowl 使用公开的 `GeneralTracer` 写运行追踪。默认会输出到控制台,并在运行目录下按日期写入: ```text -Host Name: **** -OS Name: Microsoft Windows 11 Pro -OS Version: 10.0.*** Build 22*** -System Manufacturer: ASUS -System Model: System Product Name -Processor(s): Intel** Family * Model *** -Total Physical Memory: 16,194 MB -// ...更多系统信息 +Logs/generalupdate-trace yyyy-MM-dd.log ``` -### 5. 系统事件日志 +如果你的场景对启动性能、磁盘写入或控制台输出非常敏感,可以关闭追踪: -Windows 事件查看器格式的系统日志(.evtx 文件): +```csharp +GeneralTracer.SetTracingEnabled(false); -![系统事件日志](imgs/evtx.png) +var result = await new Bowl().LaunchAsync(context); ---- +GeneralTracer.SetTracingEnabled(true); +``` -## 注意事项与警告 +关闭后,Bowl 自身的诊断追踪会减少,但崩溃 Dump 和失败 JSON 的生成逻辑不依赖该开关。排查升级失败时建议保持开启;稳定生产环境可按你的性能策略关闭。 -### ⚠️ 重要提示 +## 平台差异 -1. **工作模式选择** - - `Upgrade` 模式:专门用于与 GeneralUpdate 框架集成,包含内部逻辑处理 - - `Normal` 模式:可独立使用,适合监控任何 .NET 应用程序 +| 平台 | 监控工具 | 诊断导出 | 注意事项 | +| --- | --- | --- | --- | +| Windows | 内置 ProcDump:`procdump.exe`、`procdump64.exe`、`procdump64a.exe` | 支持 `driverInfo.txt`、`systeminfo.txt`、`systemlog.evtx` | 监控工具路径来自 `TargetPath/Applications/Windows`;需要足够权限生成 Dump | +| Linux | 内置 deb/rpm 包 + `install.sh` 安装 ProcDump 后调用 `procdump` | 当前为 no-op | 支持 Ubuntu、Debian、RHEL、CentOS、Fedora、ClearOS 映射包;脚本可能需要 `sudo` | +| macOS | `/usr/bin/lldb` | 当前为 no-op | 受 SIP、调试权限、签名策略影响;当前是基础实现 | -2. **权限要求** - - Bowl 需要足够的权限来生成 Dump 文件和读取系统信息 - - 建议以管理员权限运行需要监控的应用程序 +NuGet 包会把 `Applications/**/*` 作为内容输出到构建目录。自部署时请确认这些工具文件没有被裁剪,否则平台策略可能返回“监控工具不可用”或进程启动失败。 -3. **磁盘空间** - - Dump 文件可能占用大量磁盘空间(通常 50-200 MB) - - 确保 FailDirectory 所在磁盘有足够的可用空间 +## 恢复场景 -4. **依赖项** - - Bowl 使用 ProcDump 工具生成 Dump 文件,该工具已内置在组件中 - - 无需额外安装依赖项 +假设用户从 `1.0.0` 升级到 `2.0.0`,新版本启动后立即崩溃: -### 💡 最佳实践 +1. 升级流程先把旧版本备份到 `BackupDirectory`,例如 `C:\Program Files\MyApp\2.0.0`。 +2. 新版本文件被复制到 `TargetPath`。 +3. 主程序启动,同时 Bowl 使用 `ProcessNameOrId = "MyApp.exe"` 监控启动期异常。 +4. ProcDump 捕获到未处理异常,写出 `fail\2.0.0\2.0.0_fail.dmp`。 +5. Bowl 写出 `2.0.0_fail.json`,Windows 下继续导出驱动、系统信息和最近系统日志。 +6. 因为 `WorkModel == "Upgrade"` 且 `AutoRestore == true`,Bowl 将 `BackupDirectory` 覆盖复制回 `TargetPath`。 +7. Bowl 写入 `UpgradeFail = "2.0.0"`;Core 下次检测到服务端仍返回 `2.0.0` 或更低版本时,会跳过这个已知失败版本,直到服务端提供更高版本。 +8. `OnCrash` 回调可以上传诊断包,或提示用户已经回退到可用版本。 -- **版本号管理**:为每个版本使用独立的故障目录,便于问题追踪 -- **日志清理**:定期清理旧版本的故障信息,避免磁盘空间耗尽 -- **测试验证**:在生产环境部署前,在测试环境验证监控功能 +这个机制的目标是降低“升级成功但新版本打不开”的风险:用户回到可启动版本,开发者拿到 Dump 和上下文继续修复。 ---- +## 旧 API 迁移 -## 适用平台 +旧示例中的 `GeneralUpdate.Bowl.Strategys.MonitorParameter` 已标记为过时,推荐迁移到 `BowlContext` 和异步入口: -| 产品 | 版本 | -| --------------- | ----------------- | -| .NET | 5, 6, 7, 8, 9, 10 | -| .NET Framework | 4.6.1 | -| .NET Standard | 2.0 | -| .NET Core | 2.0 | -| ASP.NET | Any | +```csharp +var oldParameter = new GeneralUpdate.Bowl.Strategys.MonitorParameter +{ + ProcessNameOrId = "MyApp.exe", + DumpFileName = "2.0.0_fail.dmp", + FailFileName = "2.0.0_fail.json", + TargetPath = installPath, + FailDirectory = Path.Combine(installPath, "fail", "2.0.0"), + BackupDirectory = Path.Combine(installPath, "2.0.0"), + WorkModel = "Upgrade", + ExtendedField = "2.0.0" +}; ---- +BowlContext context = Bowl.MapToContext(oldParameter); +BowlResult result = await new Bowl().LaunchAsync(context); +``` + +如果是新代码,直接创建 `BowlContext`,不要再依赖旧 `MonitorParameter`。 ## 相关资源 -- **示例代码**:[查看 GitHub 示例](https://github.com/GeneralLibrary/GeneralUpdate-Samples/tree/main/src/Bowl) -- **视频教程**:[观看 Bilibili 教程](https://www.bilibili.com/video/BV1c8iyYZE7P) -- **主仓库**:[GeneralUpdate 项目](https://github.com/GeneralLibrary/GeneralUpdate) +- **示例代码**:[GeneralUpdate-Samples / Bowl](https://github.com/GeneralLibrary/GeneralUpdate-Samples/tree/main/src/Bowl) +- **主仓库**:[GeneralUpdate](https://github.com/GeneralLibrary/GeneralUpdate)