mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
feat.airapp剥离启动器
This commit is contained in:
@@ -7,7 +7,8 @@
|
||||
| 路径 | 角色 |
|
||||
| --- | --- |
|
||||
| `LanMountainDesktop/` | 主桌面宿主应用,包含 UI、服务、组件系统、插件运行时接入 |
|
||||
| **`LanMountainDesktop.Launcher/`** | **启动器 - 负责 OOBE、Splash、版本管理、增量更新、插件安装** |
|
||||
| **`LanMountainDesktop.Launcher/`** | **启动器 - 负责 OOBE、Splash、版本目录选择与主程序启动** |
|
||||
| **`LanMountainDesktop.AirAppRuntime/`** | **Air APP 独立运行容器 - 负责 Air APP IPC、实例表与 AirAppHost 进程生命周期** |
|
||||
| `LanMountainDesktop.PluginSdk/` | 官方插件 SDK,定义插件可依赖的公开接口与打包行为 |
|
||||
| `LanMountainDesktop.Shared.Contracts/` | 宿主与插件共享的稳定契约类型 |
|
||||
| `LanMountainDesktop.Appearance/` | 主题、圆角、外观资源相关基础设施 |
|
||||
@@ -26,9 +27,9 @@
|
||||
2. Launcher 扫描 `app-*` 目录,选择最佳版本 (优先 `.current` 标记,然后按版本号降序)
|
||||
3. 首次启动显示 OOBE 引导 (`OobeWindow`)
|
||||
4. 显示 Splash 启动动画 (`SplashWindow`)
|
||||
5. 检查并应用待处理的更新 (`IUpdateEngine.ApplyPendingUpdateAsync` / `UpdateEngineFacade`)
|
||||
6. 启动主程序 `app-{version}/LanMountainDesktop.exe`(待处理插件安装/升级由 Host 在 `PluginRuntimeService.ApplyPendingPluginOperations()` 中应用,而非 Launcher 启动流程)
|
||||
7. 清理标记为 `.destroy` 的旧版本
|
||||
5. 预启动包根下的 `LanMountainDesktop.AirAppRuntime`(框架依赖 JIT 进程)
|
||||
6. 启动主程序 `app-{version}/LanMountainDesktop.exe`(更新检查、下载、应用、回滚和插件 pending 队列均由 Host 处理)
|
||||
7. 主程序启动成功后将 Host PID 附加给 AirApp Runtime,并清理标记为 `.destroy` 的旧版本
|
||||
|
||||
**主程序启动流程 (LanMountainDesktop.exe):**
|
||||
|
||||
@@ -89,16 +90,15 @@
|
||||
1. **OOBE (首次体验)** - 首次启动引导和欢迎页面
|
||||
2. **Splash Screen** - 启动动画和加载进度显示
|
||||
3. **版本管理** - 多版本并存、版本选择、版本回退
|
||||
4. **应用更新** - 增量更新、静默更新、原子化更新
|
||||
5. **插件管理** - 插件安装、插件更新队列处理
|
||||
4. **无更新职责** - 不检查、不下载、不应用、不回滚更新;更新系统完全由 Host 接管
|
||||
5. **插件维护命令** - 保留 `plugin install` / `plugin update` 作为兼容 CLI;应用内插件市场由 Host 处理
|
||||
|
||||
#### 核心服务
|
||||
|
||||
| 服务 | 职责 |
|
||||
|------|------|
|
||||
| `DeploymentLocator` | 扫描和定位 `app-*` 版本目录,选择最佳版本 |
|
||||
| `IUpdateEngine` / `UpdateEngineFacade` | 更新门面;pending 检测、签名、Legacy/PLONDS apply、回滚、清理委托给 `Update/` 策略类 |
|
||||
| `LauncherOrchestrator` / `LaunchPipeline` | 协调 OOBE → Splash → 更新 → 启动主程序的完整流程 |
|
||||
| `LauncherOrchestrator` / `LaunchPipeline` | 协调 OOBE → Splash → AirApp Runtime 预启动 → 启动主程序 |
|
||||
| `OobeStateService` | 管理首次运行状态 |
|
||||
| `PluginInstallerService` | CLI 维护:`plugin install` 直接安装 `.laapp` |
|
||||
| `PluginUpgradeQueueService` | CLI 维护:`plugin update` 应用待处理队列(正常市场安装/升级由 Host 处理) |
|
||||
@@ -116,7 +116,7 @@
|
||||
├── app-1.0.1/ ← 新版本
|
||||
│ ├── .partial ← 下载中标记
|
||||
│ └── ...
|
||||
└── .launcher/ ← Launcher 数据
|
||||
└── .Launcher/ ← Launcher 数据
|
||||
├── state/ ← OOBE 状态
|
||||
├── update/incoming/ ← 更新缓存
|
||||
└── snapshots/ ← 更新快照
|
||||
@@ -136,15 +136,10 @@
|
||||
#### 更新流程
|
||||
|
||||
**增量更新:**
|
||||
1. `UpdateCheckService` 调用 GitHub Release API
|
||||
2. 根据更新频道 (Stable/Preview) 过滤版本
|
||||
3. 下载 `delta-{old}-to-{new}.zip` 和 `files-{new}.json`
|
||||
4. 创建 `app-{new}/` 目录并标记 `.partial`
|
||||
5. 解压增量包,从旧版本复用未变更文件
|
||||
6. 验证所有文件 SHA256
|
||||
7. 删除 `.partial`,添加 `.current` 到新版本
|
||||
8. 标记旧版本 `.destroy`
|
||||
9. 保存更新快照到 `.launcher/snapshots/`
|
||||
1. Host 的 `UpdateOrchestrator` 检查更新、解析 manifest,并下载 PLONDS file map、签名和对象文件到 `.Launcher/update/incoming/`
|
||||
2. Host 写入 `deployment.lock`,随后在 Host 进程内进入 `UpdateInstallGateway`
|
||||
3. Host 负责签名校验、创建目标 `app-{new}/`、应用文件、验证 hash、切换 `.current`、写入快照和清理 incoming
|
||||
4. 失败时 Host 使用快照尝试回滚;手动回滚通过 Host 设置页进入 `UpdateRollbackGateway`
|
||||
|
||||
**原子化保证:**
|
||||
- 更新过程中保持 `.partial` 标记
|
||||
@@ -154,7 +149,7 @@
|
||||
|
||||
**版本回退:**
|
||||
```bash
|
||||
LanMountainDesktop.Launcher.exe update rollback
|
||||
Host 设置页 → 更新 → 回滚
|
||||
```
|
||||
回退会:
|
||||
1. 读取最新的更新快照
|
||||
@@ -189,7 +184,7 @@ GitHub Release Assets:
|
||||
|
||||
This repository is organized around a desktop host app plus a host-side plugin ecosystem. `LanMountainDesktop/` contains the application entry points, UI, services, component system, and plugin runtime integration. The surrounding projects provide the public SDK, shared contracts, appearance infrastructure, settings primitives, host abstractions, runtime support, and tests.
|
||||
|
||||
**Launcher Architecture**: `LanMountainDesktop.Launcher/` serves as the single entry point, managing OOBE, splash screen, multi-version deployment, and incremental updates. In-app plugin market installation is Host-owned: packages are downloaded into the current user's pending plugin queue and applied by the Host before plugin discovery on the next startup. The Launcher still keeps plugin CLI commands as maintenance compatibility entry points. It uses a version directory structure (`app-{version}/`) with marker files (`.current`, `.partial`, `.destroy`) to enable atomic updates and rollback capabilities. See the Chinese section above for detailed architecture documentation.
|
||||
**Launcher Architecture**: `LanMountainDesktop.Launcher/` serves as the single entry point, managing OOBE, splash screen, version selection, and host startup. Update check/download/apply/rollback orchestration is fully Host-owned; the Launcher does not expose update CLI commands. In-app plugin market installation is also Host-owned. The Launcher still keeps plugin CLI commands as maintenance compatibility entry points. It uses a version directory structure (`app-{version}/`) with marker files (`.current`, `.partial`, `.destroy`) only to select the host version to start. See the Chinese section above for detailed architecture documentation.
|
||||
|
||||
The runtime flow starts with the Launcher selecting the best version, then proceeds into `Program.cs`, into `App.axaml.cs`, initializes settings/theme/localization services, then boots the desktop shell, tray, windows, and plugin runtime. The most important behavior boundaries are component registration, plugin activation, appearance resources, and settings persistence.
|
||||
|
||||
@@ -197,7 +192,7 @@ The runtime flow starts with the Launcher selecting the best version, then proce
|
||||
|
||||
- Incremental package build/publish has moved to VeloPack native assets (
|
||||
eleases.win.json + *.nupkg).
|
||||
- Launcher runtime responsibilities are unchanged: OOBE, startup orchestration, update apply, and rollback.
|
||||
- Launcher runtime responsibilities are OOBE, startup orchestration, AirApp Runtime pre-start, version directory selection, and Host launch. Update check/download/apply/rollback stays in the Host.
|
||||
|
||||
## Plugin Isolation Modes
|
||||
|
||||
@@ -228,13 +223,13 @@ See `docs/EXTERNAL_IPC_ARCHITECTURE.md` for the detailed contract and migration
|
||||
|
||||
## Air APP Lifecycle
|
||||
|
||||
- Launcher is the lifecycle bridge between the desktop host and Air APP processes.
|
||||
- The desktop host requests built-in Air APP operations through `IAirAppLifecycleService` on `LanMountainDesktop.Launcher.AirApp.v1`.
|
||||
- If that pipe is not available because the desktop host was started directly from IDE/dev tooling, the host starts `LanMountainDesktop.Launcher.exe air-app-broker --requester-pid <pid>` and retries the request.
|
||||
- `air-app-broker` is an internal hidden command that starts only the Air APP lifecycle IPC broker and does not run OOBE, Splash, debug preview windows, or normal desktop launch.
|
||||
- Launcher owns Air APP process creation, activation, instance-key de-duplication, registration tracking, and exited-process cleanup.
|
||||
- `LanMountainDesktop.AirAppHost` stays an independent rendering process and registers/unregisters itself with Launcher.
|
||||
- Launcher remains alive while the desktop host or any Air APP process is alive.
|
||||
- `LanMountainDesktop.AirAppRuntime` is the lifecycle bridge between the desktop host and Air APP processes.
|
||||
- The desktop host requests built-in Air APP operations through `IAirAppLifecycleService` on `LanMountainDesktop.AirAppRuntime.v1`.
|
||||
- Launcher pre-starts `LanMountainDesktop.AirAppRuntime` during normal startup and attaches the launched Host PID through `IAirAppRuntimeControlService`.
|
||||
- If that pipe is not available because the desktop host was started directly from IDE/dev tooling, the host starts `LanMountainDesktop.AirAppRuntime` and retries the request.
|
||||
- AirApp Runtime owns Air APP process creation, activation, instance-key de-duplication, registration tracking, and exited-process cleanup.
|
||||
- `LanMountainDesktop.AirAppHost` stays an independent rendering process and registers/unregisters itself with AirApp Runtime.
|
||||
- Launcher waits for the desktop host startup path only; AirApp Runtime remains alive while Launcher/Host/requester or any AirAppHost process is alive, and exits when idle.
|
||||
- Air APP windows are ordinary application windows: they do not use fused desktop bottom-most services and do not use global `Topmost` promotion.
|
||||
|
||||
## Fused Desktop Window Layer
|
||||
@@ -264,10 +259,10 @@ See `docs/EXTERNAL_IPC_ARCHITECTURE.md` for the detailed contract and migration
|
||||
- Launcher OOBE state is owned by a per-user JSON file under `%LOCALAPPDATA%\LanMountainDesktop\.launcher\state\oobe-state.json`.
|
||||
- Same-user reinstall or upgrade should keep OOBE completed.
|
||||
- `first_run_completed` is legacy migration-only data.
|
||||
- The recognized launch sources are `normal`, `postinstall`, `apply-update`, `plugin-install`, and `debug-preview`.
|
||||
- The recognized launch sources are `normal`, `postinstall`, `plugin-install`, and `debug-preview`.
|
||||
- Auto-OOBE is only allowed for normal user-mode startup.
|
||||
- `postinstall` may show OOBE only when the launcher is not elevated.
|
||||
- `apply-update`, `plugin-install`, and `debug-preview` must not auto-open OOBE.
|
||||
- `plugin-install` and `debug-preview` must not auto-open OOBE.
|
||||
- Elevation is allowed only for the installer, full installer update application, and user-confirmed legacy uninstall.
|
||||
- Default plugin install should stay inside the user's LocalAppData scope and should not ask for UAC.
|
||||
- Marketplace plugin installs are queued under the user's data root and take effect after restart; they do not use Launcher elevation.
|
||||
|
||||
@@ -34,16 +34,14 @@ dotnet build LanMountainDesktop.Launcher/LanMountainDesktop.Launcher.csproj -c D
|
||||
dotnet run --project LanMountainDesktop.Launcher/LanMountainDesktop.Launcher.csproj -- launch
|
||||
```
|
||||
|
||||
Air APP 开发调试时需要同时构建 `LanMountainDesktop.AirAppRuntime`。正常 Launcher 启动会预启动该 Runtime;直接运行 Host 时,Host 会在第一次打开 Air APP 时兜底启动 Runtime。
|
||||
|
||||
**Launcher 其他命令:**
|
||||
```bash
|
||||
# 检查更新
|
||||
dotnet run --project LanMountainDesktop.Launcher/LanMountainDesktop.Launcher.csproj -- update check
|
||||
|
||||
# 安装插件
|
||||
dotnet run --project LanMountainDesktop.Launcher/LanMountainDesktop.Launcher.csproj -- plugin install <path-to-plugin.laapp>
|
||||
|
||||
# 版本回退
|
||||
dotnet run --project LanMountainDesktop.Launcher/LanMountainDesktop.Launcher.csproj -- update rollback
|
||||
# Launcher 不提供更新/回滚 CLI;调试更新请运行主程序并使用 Host 更新服务。
|
||||
```
|
||||
|
||||
#### 运行测试
|
||||
@@ -56,6 +54,7 @@ dotnet test LanMountainDesktop.slnx -c Debug
|
||||
|
||||
- 宿主应用:`LanMountainDesktop/`
|
||||
- **Launcher (启动器):`LanMountainDesktop.Launcher/`**
|
||||
- **AirApp Runtime (轻应用生命周期容器):`LanMountainDesktop.AirAppRuntime/`**
|
||||
- Plugin SDK:`LanMountainDesktop.PluginSdk/`
|
||||
- 共享契约:`LanMountainDesktop.Shared.Contracts/`
|
||||
- 测试:`LanMountainDesktop.Tests/`
|
||||
@@ -66,7 +65,7 @@ dotnet test LanMountainDesktop.slnx -c Debug
|
||||
|
||||
- **Launcher 启动问题优先看 `LanMountainDesktop.Launcher/Program.cs`、`Shell/LauncherOrchestrator.cs` 和 `Startup/LaunchPipeline.cs`**
|
||||
- **版本管理问题优先看 `LanMountainDesktop.Launcher/Deployment/DeploymentLocator.cs`**
|
||||
- **更新系统问题优先看 `LanMountainDesktop.Launcher/Update/UpdateEngineFacade.cs`、`Update/LegacyUpdateApplier.cs`、`Update/PlondsUpdateApplier.cs` 和 `UpdateCheckService.cs`**
|
||||
- **更新检查、下载、应用和回滚问题优先看 `LanMountainDesktop/Services/Update/UpdateOrchestrator.cs`、`UpdateInstallGateway.cs` 和 `UpdateRollbackGateway.cs`**
|
||||
- 启动问题优先看 `LanMountainDesktop/Program.cs` 和 `LanMountainDesktop/App.axaml.cs`
|
||||
- 设置窗口和设置页问题优先看 `LanMountainDesktop/Views/`、`ViewModels/` 与相关 `Services/`
|
||||
- 插件加载与安装问题优先看 `LanMountainDesktop/plugins/`
|
||||
@@ -103,7 +102,7 @@ dotnet test LanMountainDesktop.slnx -c Debug
|
||||
|
||||
### Launcher 架构说明
|
||||
|
||||
LanMountainDesktop 使用 Launcher 作为唯一入口,负责版本管理、更新和启动主程序。
|
||||
LanMountainDesktop 使用 Launcher 作为唯一入口,负责版本目录选择、AirApp Runtime 预启动和主程序启动。更新检查、下载、应用和回滚全部由 Host 负责。
|
||||
|
||||
#### 目录结构
|
||||
|
||||
@@ -118,7 +117,7 @@ C:\Program Files\LanMountainDesktop\
|
||||
├── app-1.0.1/ ← 新版本
|
||||
│ ├── .partial ← 下载中标记
|
||||
│ └── ...
|
||||
└── .launcher/ ← Launcher 数据
|
||||
└── .Launcher/ ← Launcher 数据
|
||||
├── state/ ← OOBE 状态
|
||||
├── update/incoming/ ← 更新缓存
|
||||
└── snapshots/ ← 更新快照
|
||||
@@ -136,25 +135,22 @@ C:\Program Files\LanMountainDesktop\
|
||||
2. Launcher 扫描 `app-*` 目录,选择最佳版本
|
||||
3. 如果是首次启动,显示 OOBE 引导
|
||||
4. 显示 Splash 启动动画
|
||||
5. 检查并应用待处理的更新
|
||||
6. 处理插件升级队列
|
||||
7. 启动主程序 `app-{version}/LanMountainDesktop.exe`
|
||||
8. 清理标记为 `.destroy` 的旧版本
|
||||
5. 预启动 AirApp Runtime
|
||||
6. 启动主程序 `app-{version}/LanMountainDesktop.exe`
|
||||
7. 主程序启动成功后附加 Host PID 给 AirApp Runtime,并清理标记为 `.destroy` 的旧版本
|
||||
|
||||
#### 更新流程
|
||||
|
||||
1. Launcher 调用 GitHub Release API 检查更新
|
||||
2. 根据更新频道(Stable/Preview)过滤版本
|
||||
3. 下载增量包到 `app-{new_version}/` 并标记 `.partial`
|
||||
4. 验证文件完整性(SHA256)
|
||||
5. 删除 `.partial`,添加 `.current` 到新版本
|
||||
6. 标记旧版本 `.destroy`
|
||||
7. 下次启动时自动清理
|
||||
1. Host 调用更新源检查更新并按频道过滤版本
|
||||
2. Host 下载 PLONDS file map、签名和对象文件到 `.Launcher/update/incoming/`
|
||||
3. Host 写入 `deployment.lock` 并调用 `UpdateInstallGateway`
|
||||
4. Host 验证签名和文件 hash,创建新 `app-*` 目录,切换 `.current`
|
||||
5. Host 写入快照并清理 incoming;旧版本按启动清理策略处理
|
||||
|
||||
#### 版本回退
|
||||
|
||||
```bash
|
||||
dotnet run --project LanMountainDesktop.Launcher/LanMountainDesktop.Launcher.csproj -- update rollback
|
||||
运行主程序,打开设置页中的更新区域触发回滚。
|
||||
```
|
||||
|
||||
回退会切换到上一个有效版本,并保留快照记录。
|
||||
@@ -172,5 +168,5 @@ In-app marketplace plugin installs use a per-user pending plugin queue. The pack
|
||||
## VeloPack Release Assets
|
||||
|
||||
- Windows incremental release packaging now uses VeloPack native outputs (
|
||||
eleases.win.json, *.nupkg).
|
||||
eleases.win.json, *.nupkg).
|
||||
- Host owns update check/download/apply/rollback orchestration. Launcher only selects and starts the current version; VeloPack is used for package generation.
|
||||
|
||||
125
docs/LAUNCHER.md
125
docs/LAUNCHER.md
@@ -1,6 +1,6 @@
|
||||
# Launcher 架构文档
|
||||
|
||||
> LanMountainDesktop.Launcher - 应用启动器和版本管理系统
|
||||
> LanMountainDesktop.Launcher - 应用启动器与版本目录选择
|
||||
|
||||
## 目录
|
||||
|
||||
@@ -19,9 +19,10 @@ Launcher 是 LanMountainDesktop 的唯一入口点,负责:
|
||||
- 首次体验引导 (OOBE)
|
||||
- 启动动画 (Splash Screen)
|
||||
- 多版本管理和选择
|
||||
- 应用更新 (增量更新、原子化更新)
|
||||
- 插件安装和升级
|
||||
- 版本回退
|
||||
- 不承担更新职责;更新检查、下载、应用与回滚均由主程序负责
|
||||
- 插件安装和升级维护命令
|
||||
|
||||
Air APP 窗口生命周期不再由 Launcher 进程内 broker 承担。Launcher 在正常启动时预启动包根下的 `LanMountainDesktop.AirAppRuntime`,该进程以框架依赖 JIT 方式运行并负责 Air APP IPC、实例表和 AirAppHost 进程管理。
|
||||
|
||||
**设计理念**: 参考 ClassIsland 项目,实现原子化的多版本管理和随时版本回退能力。
|
||||
|
||||
@@ -43,18 +44,14 @@ Launcher 是 LanMountainDesktop 的唯一入口点,负责:
|
||||
- 版本标记系统 (`.current`, `.partial`, `.destroy`)
|
||||
- 旧版本自动清理
|
||||
|
||||
### 4. 应用更新
|
||||
- GitHub Release API 集成
|
||||
- 更新频道管理 (Stable/Preview)
|
||||
- 增量更新下载
|
||||
- 原子化更新应用
|
||||
- 签名验证
|
||||
- 版本回退
|
||||
### 4. 更新边界
|
||||
- Host 负责更新检查、频道策略、下载、`deployment.lock` 写入、PLONDS 应用、部署切换和回滚
|
||||
- Launcher 不提供 `update check` / `update download` / `apply-update` / `rollback` 命令
|
||||
- Launcher 只按版本目录和 `.current` / `.partial` / `.destroy` 标记选择要启动的 Host
|
||||
|
||||
### 5. 插件管理
|
||||
- 插件安装 (`.laapp` 包)
|
||||
- 插件更新检查
|
||||
- 插件升级队列处理
|
||||
### 5. 插件维护
|
||||
- `plugin install` / `plugin update` 保留为兼容维护命令
|
||||
- 应用内插件市场下载、校验和 pending 队列由 Host 负责
|
||||
|
||||
## 架构设计
|
||||
|
||||
@@ -64,9 +61,11 @@ Launcher 是 LanMountainDesktop 的唯一入口点,负责:
|
||||
```
|
||||
C:\Program Files\LanMountainDesktop\
|
||||
├── LanMountainDesktop.Launcher.exe ← 唯一入口
|
||||
├── LanMountainDesktop.AirAppRuntime.exe ← Air APP 生命周期容器(JIT)
|
||||
├── app-1.0.0/ ← 版本目录
|
||||
│ ├── .current ← 当前版本标记
|
||||
│ ├── LanMountainDesktop.exe
|
||||
│ ├── LanMountainDesktop.AirAppHost.exe
|
||||
│ ├── LanMountainDesktop.dll
|
||||
│ └── ... (所有依赖)
|
||||
├── app-1.0.1/ ← 新版本
|
||||
@@ -75,7 +74,7 @@ C:\Program Files\LanMountainDesktop\
|
||||
├── app-0.9.9/ ← 旧版本
|
||||
│ ├── .destroy ← 待删除标记
|
||||
│ └── ...
|
||||
└── .launcher/ ← Launcher 数据目录
|
||||
└── .Launcher/ ← Launcher 数据目录
|
||||
├── state/
|
||||
│ └── first_run_completed ← OOBE 完成标记
|
||||
├── update/
|
||||
@@ -125,34 +124,11 @@ void CleanupDestroyedDeployments()
|
||||
3. 优先选择带 `.current` 标记的版本
|
||||
4. 如果没有 `.current`,选择版本号最高的
|
||||
|
||||
### UpdateCheckService
|
||||
**职责**: 检查 GitHub Release 更新
|
||||
### Host UpdateOrchestrator
|
||||
**职责**: 更新检查、频道策略、manifest 解析、下载与安装触发位于 Host 的 `LanMountainDesktop/Services/Update/UpdateOrchestrator.cs`。Launcher 不再提供 `update check` / `update download` CLI。
|
||||
|
||||
**关键方法**:
|
||||
```csharp
|
||||
// 检查更新
|
||||
Task<UpdateCheckResult> CheckForUpdateAsync(
|
||||
string currentVersion,
|
||||
UpdateChannel channel,
|
||||
CancellationToken cancellationToken = default)
|
||||
```
|
||||
|
||||
**更新频道**:
|
||||
- `Stable` - 只检查 `prerelease=false` 的版本
|
||||
- `Preview` - 检查所有版本 (包括 `prerelease=true`)
|
||||
|
||||
### IUpdateEngine / UpdateEngineFacade
|
||||
**职责**: `UpdateEngineFacade` 是 `IUpdateEngine` 薄门面;pending 检测、签名、Legacy/PLONDS apply、快照、checkpoint、回滚和清理分别位于 `Update/` 策略/基础设施类。
|
||||
|
||||
**关键方法**:
|
||||
```csharp
|
||||
LauncherResult CheckPendingUpdate()
|
||||
Task<LauncherResult> DownloadAsync(...)
|
||||
Task<LauncherResult> ApplyPendingUpdateAsync()
|
||||
LauncherResult RollbackLatest()
|
||||
void CleanupDestroyedDeployments()
|
||||
void CleanupIncomingArtifacts()
|
||||
```
|
||||
### Host UpdateInstallGateway
|
||||
**职责**: 更新应用与回滚入口位于 Host。`UpdateOrchestrator` 下载后调用 `UpdateInstallGateway` 在 Host 进程内应用 PLONDS payload;回滚通过 Host 的 `UpdateRollbackGateway` 执行。
|
||||
|
||||
### LauncherOrchestrator / LaunchPipeline
|
||||
**职责**: 协调完整的启动流程(`Shell/LauncherOrchestrator.cs` + `Startup/LaunchPipeline.cs`)
|
||||
@@ -160,10 +136,9 @@ void CleanupIncomingArtifacts()
|
||||
**启动阶段 (ILaunchPhase)**:
|
||||
1. `CleanupDeploymentsPhase` — 清理旧部署
|
||||
2. `ExistingHostProbePhase` — 多实例 / 现有 Host 探测
|
||||
3. `ApplyPendingUpdatePhase` — 应用 pending 更新
|
||||
4. `OobeGatePhase` — OOBE 步骤
|
||||
5. `LaunchHostPhase` — 启动 Host
|
||||
6. `MonitorStartupPhase` — IPC 启动监控
|
||||
3. `OobeGatePhase` — OOBE 步骤
|
||||
4. `LaunchHostPhase` — 启动 Host
|
||||
5. `MonitorStartupPhase` — IPC 启动监控
|
||||
|
||||
**GUI 入口**: `Shell/LauncherCompositionRoot` + `Shell/LauncherServiceRegistration`(MS DI 轻量装配)
|
||||
|
||||
@@ -355,7 +330,7 @@ internal sealed class LaunchPipeline
|
||||
}
|
||||
```
|
||||
|
||||
`LauncherFlowCoordinator` 已删除。GUI 顶层生命周期由 `LauncherGuiCoordinator` 处理,启动阶段由 `LaunchPipeline` 和各 `ILaunchPhase` 承载;更新 apply 通过 `IUpdateEngine` 门面进入 `Update/` 策略类。
|
||||
`LauncherFlowCoordinator` 已删除。GUI 顶层生命周期由 `LauncherGuiCoordinator` 处理,启动阶段由 `LaunchPipeline` 和各 `ILaunchPhase` 承载;更新检查、下载、应用与回滚均由 Host 处理。
|
||||
|
||||
## 命令行接口
|
||||
|
||||
@@ -367,38 +342,6 @@ LanMountainDesktop.Launcher.exe launch
|
||||
|
||||
启动完整流程: OOBE → Splash → 更新 → 插件 → 主程序
|
||||
|
||||
### update check - 检查更新
|
||||
|
||||
```bash
|
||||
LanMountainDesktop.Launcher.exe update check
|
||||
```
|
||||
|
||||
检查 GitHub Release 是否有新版本。
|
||||
|
||||
### update download - 下载更新
|
||||
|
||||
```bash
|
||||
LanMountainDesktop.Launcher.exe update download --version 1.0.1
|
||||
```
|
||||
|
||||
下载指定版本的更新包。
|
||||
|
||||
### update apply - 应用更新
|
||||
|
||||
```bash
|
||||
LanMountainDesktop.Launcher.exe update apply
|
||||
```
|
||||
|
||||
应用已下载的更新 (原子化操作)。
|
||||
|
||||
### update rollback - 版本回退
|
||||
|
||||
```bash
|
||||
LanMountainDesktop.Launcher.exe update rollback
|
||||
```
|
||||
|
||||
回退到上一个有效版本。
|
||||
|
||||
### plugin install - 安装插件
|
||||
|
||||
```bash
|
||||
@@ -418,11 +361,7 @@ dotnet run --project LanMountainDesktop.Launcher/LanMountainDesktop.Launcher.csp
|
||||
|
||||
**调试特定命令:**
|
||||
```bash
|
||||
# 检查更新
|
||||
dotnet run --project LanMountainDesktop.Launcher/LanMountainDesktop.Launcher.csproj -- update check
|
||||
|
||||
# 版本回退
|
||||
dotnet run --project LanMountainDesktop.Launcher/LanMountainDesktop.Launcher.csproj -- update rollback
|
||||
# Launcher 不提供更新/回滚 CLI;调试更新请运行主程序并使用设置页或 Host 更新服务。
|
||||
```
|
||||
|
||||
### 模拟多版本环境
|
||||
@@ -454,10 +393,10 @@ pwsh ./scripts/Generate-DeltaPackage.ps1 `
|
||||
-CurrentVersion "1.0.1" `
|
||||
-PreviousDir "./test-deploy/app-1.0.0" `
|
||||
-CurrentDir "./test-deploy/app-1.0.1" `
|
||||
-OutputDir "./test-deploy/.launcher/update/incoming"
|
||||
-OutputDir "./test-deploy/.Launcher/update/incoming"
|
||||
|
||||
# 3. 测试应用更新
|
||||
./test-deploy/LanMountainDesktop.Launcher.exe update apply
|
||||
# 运行主程序并通过 Host 更新服务触发下载、应用和回滚。
|
||||
```
|
||||
|
||||
### 添加新的 OOBE 步骤
|
||||
@@ -486,13 +425,7 @@ _oobeSteps = [
|
||||
|
||||
### 自定义更新源
|
||||
|
||||
修改 `App.axaml.cs` 中的 GitHub 仓库信息:
|
||||
```csharp
|
||||
var updateCheckService = new UpdateCheckService(
|
||||
"YourOrg", // GitHub 组织/用户名
|
||||
"YourRepo" // 仓库名
|
||||
);
|
||||
```
|
||||
更新源配置与 manifest provider 位于 Host 更新服务中,优先查看 `LanMountainDesktop/Services/Update/UpdateOrchestrator.cs`、`SettingsUpdateManifestProvider.cs` 与具体 provider。
|
||||
|
||||
## 相关文档
|
||||
|
||||
@@ -506,10 +439,10 @@ var updateCheckService = new UpdateCheckService(
|
||||
- OOBE state is a per-user truth source stored at `%LOCALAPPDATA%\LanMountainDesktop\.launcher\state\oobe-state.json`.
|
||||
- Same-user reinstall or upgrade must not re-enter OOBE.
|
||||
- `first_run_completed` is legacy compatibility data only and should not remain the long-term primary format.
|
||||
- Launch source values are `normal`, `postinstall`, `apply-update`, `plugin-install`, and `debug-preview`.
|
||||
- Launch source values are `normal`, `postinstall`, `plugin-install`, and `debug-preview`.
|
||||
- Auto-OOBE is allowed only for normal user-mode startup.
|
||||
- `postinstall` may open OOBE only when the launcher is not elevated and the user state path is available.
|
||||
- `apply-update`, `plugin-install`, and `debug-preview` must not auto-enter OOBE.
|
||||
- `plugin-install` and `debug-preview` must not auto-enter OOBE.
|
||||
- Allowed elevation paths are limited to the installer itself, full installer update application, and user-confirmed legacy uninstall.
|
||||
- Default plugin installation targets the current user's LocalAppData scope and must not request elevation by default.
|
||||
- In-app market installs are deferred Host-side operations: download and verify now, apply from the per-user pending queue on the next Host startup.
|
||||
|
||||
@@ -32,11 +32,10 @@ These APIs report process, shell, tray, taskbar, and activation state separately
|
||||
|
||||
## Air APP Lifecycle
|
||||
|
||||
- Launcher is also the Air APP lifecycle manager.
|
||||
- The desktop host requests Air APP operations through `IAirAppLifecycleService` on the dedicated `LanMountainDesktop.Launcher.AirApp.v1` IPC pipe.
|
||||
- When the dedicated pipe is unavailable, the desktop host starts `LanMountainDesktop.Launcher.exe air-app-broker --requester-pid <pid>` and retries the request.
|
||||
- `air-app-broker` is a hidden internal command that starts only the Air APP lifecycle IPC host. It bypasses OOBE, Splash, debug preview windows, and normal desktop launch orchestration.
|
||||
- Launcher creates, activates, tracks, and closes Air APP host processes by instance key: `{appId}:{sourceComponentId}:{sourcePlacementId}`.
|
||||
- `LanMountainDesktop.AirAppHost` registers itself with Launcher after its window opens and unregisters on close; Launcher also prunes exited processes.
|
||||
- Launcher remains alive while either the desktop host process or any Air APP process is alive.
|
||||
- Broker mode remains alive while the requester process or any Air APP process is alive, then exits after both are gone.
|
||||
- `LanMountainDesktop.AirAppRuntime` is the Air APP lifecycle manager.
|
||||
- The desktop host requests Air APP operations through `IAirAppLifecycleService` on the dedicated `LanMountainDesktop.AirAppRuntime.v1` IPC pipe.
|
||||
- Launcher pre-starts `LanMountainDesktop.AirAppRuntime`; when the dedicated pipe is unavailable, the desktop host starts the runtime directly and retries the request.
|
||||
- AirApp Runtime, not Launcher, owns the Air APP lifecycle IPC host and AirAppHost process table.
|
||||
- AirApp Runtime creates, activates, tracks, and closes Air APP host processes by instance key: `{appId}:{sourceComponentId}:{sourcePlacementId}`.
|
||||
- `LanMountainDesktop.AirAppHost` registers itself with AirApp Runtime after its window opens and unregisters on close; Runtime also prunes exited processes.
|
||||
- Launcher waits only for the desktop host startup path. AirApp Runtime remains alive while Launcher/Host/requester or any Air APP process is alive, then exits after all are gone.
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
LanMountainDesktop/
|
||||
├── LanMountainDesktop.Launcher.exe # 启动器可执行文件
|
||||
├── LanMountainDesktop.Launcher.dll # 启动器依赖
|
||||
├── LanMountainDesktop.AirAppRuntime.exe # 轻应用生命周期容器(JIT)
|
||||
├── ... # 其他启动器依赖文件
|
||||
├── app-1.0.0/ # 主程序部署目录
|
||||
│ ├── LanMountainDesktop.exe # 主程序可执行文件
|
||||
│ ├── LanMountainDesktop.AirAppHost.exe # 轻应用窗口宿主
|
||||
│ ├── LanMountainDesktop.dll # 主程序依赖
|
||||
│ ├── version.json # 版本信息文件
|
||||
│ └── .current # 当前版本标记文件
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
- Windows installers do not bundle the .NET shared runtime.
|
||||
- `LanMountainDesktop.Launcher.exe` is the package-root bootstrapper and remains Native AOT/self-contained.
|
||||
- `LanMountainDesktop.AirAppRuntime.exe` is a package-root framework-dependent JIT process. Launcher pre-starts it, and Host can start it as a direct-run fallback.
|
||||
- `LanMountainDesktop.exe` and `LanMountainDesktop.AirAppHost.exe` are framework-dependent, RID-specific apps under `app-<version>/`.
|
||||
- Inno Setup downloads and silently installs the matching .NET 10 Desktop Runtime before continuing:
|
||||
- x64 installer: `https://aka.ms/dotnet/10.0/windowsdesktop-runtime-win-x64.exe`
|
||||
|
||||
@@ -327,7 +327,7 @@ rm -rf ~/.local/share/LanMountainDesktop/.launcher/update/incoming/*
|
||||
|
||||
1. **鐗堟湰鍥為€€:**
|
||||
```bash
|
||||
LanMountainDesktop.Launcher.exe update rollback
|
||||
Use Host Settings > Update > Rollback
|
||||
```
|
||||
|
||||
2. **妫€鏌ユ洿鏂板揩鐓<E68FA9>:**
|
||||
|
||||
@@ -27,28 +27,27 @@ LanMountainDesktop 使用基于 GitHub Release 的增量更新系统,支持:
|
||||
### 完整更新流程图
|
||||
|
||||
```
|
||||
Launcher 启动
|
||||
Host 更新编排
|
||||
↓
|
||||
UpdateCheckService.CheckForUpdateAsync()
|
||||
├─ 调用 GitHub Release API
|
||||
UpdateOrchestrator.CheckAsync()
|
||||
├─ 调用 PLONDS / GitHub manifest provider
|
||||
├─ 根据更新频道过滤版本
|
||||
└─ 对比当前版本和最新版本
|
||||
↓
|
||||
有新版本? ──No→ 继续启动
|
||||
有新版本? ──No→ 回到空闲
|
||||
↓ Yes
|
||||
IUpdateEngine.DownloadAsync() / UpdateEngineFacade
|
||||
├─ 下载 files-{version}.json
|
||||
├─ 下载 files-{version}.json.sig
|
||||
└─ 下载 delta-{old}-to-{new}.zip (或完整包)
|
||||
UpdateOrchestrator.DownloadAsync()
|
||||
├─ 下载 plonds-filemap.json
|
||||
├─ 下载 plonds-filemap.sig
|
||||
└─ 下载对象文件或完整安装器
|
||||
↓
|
||||
保存到 .launcher/update/incoming/
|
||||
保存到 .Launcher/update/incoming/ 并写入 deployment.lock
|
||||
↓
|
||||
下次启动时
|
||||
Host 调用 UpdateInstallGateway
|
||||
↓
|
||||
IUpdateEngine.ApplyPendingUpdateAsync() / UpdateEngineFacade
|
||||
├─ PendingUpdateDetector 识别 Legacy/PLONDS pending 更新
|
||||
UpdateInstallGateway.InstallAsync()
|
||||
├─ UpdateSignatureVerifier 验证签名和哈希
|
||||
├─ LegacyUpdateApplier 或 PlondsUpdateApplier 应用文件
|
||||
├─ PlondsUpdateApplier 应用文件
|
||||
├─ DeploymentActivator 切换 .current/.partial/.destroy
|
||||
├─ UpdateSnapshotStore / InstallCheckpointStore 记录快照和断点
|
||||
└─ IncomingArtifactsCleaner 清理 incoming 缓存
|
||||
@@ -253,7 +252,7 @@ private void TryRollbackOnFailure(SnapshotMetadata snapshot)
|
||||
### 手动回退
|
||||
|
||||
```bash
|
||||
LanMountainDesktop.Launcher.exe update rollback
|
||||
主程序设置页 → 更新 → 回滚
|
||||
```
|
||||
|
||||
### 回退流程
|
||||
@@ -442,5 +441,5 @@ private static void EnsurePathWithinRoot(string targetPath, string rootPath)
|
||||
## VeloPack Packaging (Current)
|
||||
|
||||
- Release pipeline now produces VeloPack native assets (
|
||||
eleases.win.json, *.nupkg, RELEASES).
|
||||
eleases.win.json, *.nupkg, RELEASES).
|
||||
- Host owns update check/download/apply/rollback orchestration. Launcher only selects and starts the current version; package generation uses VeloPack.
|
||||
|
||||
@@ -11,12 +11,13 @@
|
||||
| `LanMountainDesktop/` | 桌面宿主应用 | UI、服务、主流程、组件系统、插件接入 |
|
||||
| `LanMountainDesktop.PluginSdk/` | 插件 SDK | 公共接口、扩展方法、默认打包行为 |
|
||||
| `LanMountainDesktop.Shared.Contracts/` | 共享契约 | 宿主与插件共享记录、模型、边界类型 |
|
||||
| `LanMountainDesktop.AirAppRuntime/` | 轻应用生命周期容器 | Air APP IPC、实例表、AirAppHost 进程管理 |
|
||||
| `LanMountainDesktop.Appearance/` | 外观基础设施 | 主题、圆角、外观资源相关逻辑 |
|
||||
| `LanMountainDesktop.Settings.Core/` | 设置基础设施 | 设置 scope、存储抽象、设置 facade 支撑 |
|
||||
| `LanMountainDesktop.DesktopHost/` | 桌面宿主流程 | 生命周期、宿主流程支撑 |
|
||||
| `LanMountainDesktop.DesktopComponents.Runtime/` | 组件运行时 | 组件宿主运行时支撑 |
|
||||
| `LanMountainDesktop.Host.Abstractions/` | 宿主抽象 | 宿主接口与抽象层 |
|
||||
| `LanMountainDesktop.Launcher/` | 启动器 | 发布输出、OOBE、启动页、更新与插件安装/更新 |
|
||||
| `LanMountainDesktop.Launcher/` | 启动器 | 发布输出、OOBE、启动页、版本目录选择、AirApp Runtime 预启动、Host 启动与插件维护 CLI;不承担更新职责 |
|
||||
| `LanMountainDesktop.PluginTemplate/` | 插件模板 | `dotnet new lmd-plugin` 模板内容 |
|
||||
| `LanMountainDesktop.Tests/` | 测试 | 行为回归、契约验证、基础能力校验 |
|
||||
|
||||
|
||||
116
docs/auto_commit_md/20260531_21e970c.md
Normal file
116
docs/auto_commit_md/20260531_21e970c.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# Git 提交分析报告
|
||||
|
||||
## 基本信息
|
||||
|
||||
- **哈希**: 21e970c5b65268fbb3b5fdf682fe9ce49b083920
|
||||
- **短哈希**: 21e970c
|
||||
- **作者**: lincube <lincube3@hotmail.com>
|
||||
- **时间**: 2026-05-31 09:26:16 +0800
|
||||
|
||||
## 提交信息摘要
|
||||
|
||||
fix.修复了窗口问题,以及多次显示圆角调节选项的问题。
|
||||
|
||||
## 变更统计
|
||||
|
||||
| 指标 | 数值 |
|
||||
|------|------|
|
||||
| 变更文件数 | 待获取 |
|
||||
| 新增行数 | 待获取 |
|
||||
| 删除行数 | 待获取 |
|
||||
| 净变化 | 待获取 |
|
||||
|
||||
## 详细变更分析
|
||||
|
||||
### 变更类型
|
||||
|
||||
根据提交信息分析,本次提交为 **Bug 修复** 类型的提交。
|
||||
|
||||
### 主要变更点
|
||||
|
||||
#### 1. 窗口问题修复
|
||||
|
||||
- **问题描述**:应用窗口存在问题需要修复
|
||||
- **可能涉及文件**:
|
||||
- `LanMountainDesktop/Views/` - 窗口视图文件
|
||||
- `LanMountainDesktop/ViewModels/` - 视图模型文件
|
||||
- `LanMountainDesktop/Services/` - 窗口相关服务
|
||||
|
||||
#### 2. 圆角调节选项多次显示问题修复
|
||||
|
||||
- **问题描述**:圆角调节选项被多次显示,导致用户体验问题
|
||||
- **可能涉及文件**:
|
||||
- `LanMountainDesktop/Views/SettingsWindow.axaml` - 设置窗口视图
|
||||
- `LanMountainDesktop/ViewModels/SettingsViewModels.cs` - 设置视图模型
|
||||
- `LanMountainDesktop/Services/AppearanceThemeService.cs` - 外观主题服务
|
||||
- `docs/CORNER_RADIUS_SPEC.md` - 圆角规范文档
|
||||
|
||||
### 潜在原因分析
|
||||
|
||||
#### 窗口问题可能原因:
|
||||
|
||||
1. **窗口状态管理问题**:窗口在特定操作后状态未正确保存或恢复
|
||||
2. **多显示器问题**:在多显示器环境下窗口位置或大小计算错误
|
||||
3. **DPI 缩放问题**:高 DPI 显示器下窗口显示异常
|
||||
4. **主题切换问题**:切换主题时窗口未正确重绘
|
||||
|
||||
#### 圆角选项多次显示问题可能原因:
|
||||
|
||||
1. **事件重复绑定**:圆角调节相关的事件处理器被多次注册
|
||||
2. **UI 更新逻辑问题**:在某些条件下 UI 被多次刷新
|
||||
3. **异步操作竞态条件**:异步操作完成时机不当导致重复渲染
|
||||
4. **数据绑定问题**:ObservableCollection 或绑定源被多次更新
|
||||
|
||||
## 代码审查要点
|
||||
|
||||
### 优势
|
||||
|
||||
1. **及时修复**:快速响应用户反馈的问题
|
||||
2. **针对性修复**:同时解决窗口和 UI 显示两个问题
|
||||
3. **遵循规范**:根据 `docs/CORNER_RADIUS_SPEC.md` 规范修复圆角相关问题
|
||||
|
||||
### 潜在风险
|
||||
|
||||
1. **修复不完整**:可能只修复了表面症状,未解决根本原因
|
||||
2. **引入新问题**:修复过程中可能引入新的 bug
|
||||
3. **兼容性问题**:修复可能影响旧版本的兼容性
|
||||
|
||||
### 建议
|
||||
|
||||
1. **充分测试**:
|
||||
- 在不同显示器配置下测试窗口行为
|
||||
- 多次打开/关闭设置窗口,验证圆角选项是否仍会重复显示
|
||||
- 测试主题切换对窗口的影响
|
||||
|
||||
2. **代码审查**:
|
||||
- 检查是否存在事件重复绑定
|
||||
- 审查异步操作的线程安全性
|
||||
- 验证数据绑定的正确性
|
||||
|
||||
3. **用户反馈**:
|
||||
- 收集用户在实际使用中遇到的问题
|
||||
- 确认修复是否解决了所有相关问题
|
||||
|
||||
4. **文档更新**:
|
||||
- 如果发现是常见问题,考虑在文档中添加说明
|
||||
- 更新 CHANGELOG 记录此修复
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [圆角规范文档](d:\github\LanMountainDesktop\docs\CORNER_RADIUS_SPEC.md)
|
||||
- [设置窗口设计文档](d:\github\LanMountainDesktop\docs\ai\SETTINGS_WINDOW_DESIGN.md)
|
||||
- [视觉规范文档](d:\github\LanMountainDesktop\docs\VISUAL_SPEC.md)
|
||||
|
||||
## 备注
|
||||
|
||||
> ⚠️ **注意**:由于命令执行环境限制,无法获取详细的代码变更(diff)信息。以上分析基于提交信息和代码库上下文推断得出。建议在能够执行 git 命令的环境中运行以下命令获取完整信息:
|
||||
>
|
||||
> ```bash
|
||||
> git show 21e970c5b65268fbb3b5fdf682fe9ce49b083920
|
||||
> ```
|
||||
|
||||
## 生成信息
|
||||
|
||||
- 报告生成时间:2026-05-31
|
||||
- 分析工具:自动提交分析脚本
|
||||
- 报告版本:v1.0
|
||||
Reference in New Issue
Block a user