Files

266 lines
12 KiB
Markdown
Raw Permalink Normal View History

# SimCAE Hub 更新客户端
`update-client` 是 SimCAE Hub 的 Qt/C++ 整包更新客户端,包含 `Launcher``Updater``Bootstrap` 和一个示例 `MainApp`。它负责检查整包更新、拉取 Manifest、下载发布包、校验哈希并完成本地安装。
组件级安装、组件级更新和卸载由 Qt IFW 生成的 `maintenancetool.exe` 负责。`update-client` 不替代 MaintenanceTool,也不读取 Qt IFW 的 `Updates.xml`
## 一、当前接入方式
当前 SIMCAE 的标准接入方式是:
| 阶段 | 发生什么 |
| --- | --- |
| SDK 打包 | `update-client` 只打出 `Launcher.exe``Updater.exe``Bootstrap.exe` 和运行库 |
| SIMCAE 打包 | SIMCAE 的 `installer` 规则把 SDK 文件放进核心组件 `com.simcae.app` |
| 本地 IFW package | Hub 更新客户端位于 `package/packages/com.simcae.app/data/view/bin` |
| 上传到 Hub | 服务端校验 IFW 交付包,并自动注入最终客户配置 |
| 客户安装 | 客户从门户下载安装器,安装后得到 `maintenancetool.exe``view/bin/Launcher.exe` |
| 日常启动 | 客户通过 `Launcher.exe` 或安装器创建的快捷方式启动 SimCAE |
最终客户不需要手动填写 `app_config.json`、服务器地址、token、产品编码、平台架构或版本号。
## 二、程序组成
| 程序 | 作用 |
| --- | --- |
| `Launcher` | 客户日常启动入口,读取配置、检查整包更新、启动 `Updater` 或主程序 |
| `Updater` | 拉取 Manifest、下载发布包、校验文件、准备安装事务 |
| `Bootstrap` | 替换运行中文件,并把安装结果交回 `Updater` |
| `MainApp` | 示例主程序,用于验证 launch ticket 和启动前完整性校验 |
| `Common` | 配置、HTTP、票据、路径、Manifest 和完整性校验等公共代码 |
真实接入 SIMCAE 时,`MainApp` 只是示例程序。正式主程序是 SIMCAE 自己的 `SimCAE.exe`
## 三、在线更新链路
1. 客户启动 `Launcher.exe`
2. 客户端读取服务端注入的初始配置。
3. 首次启动时,客户端会把 `app_config.json` 中的运行配置导入本机用户配置。
4. 为减少明文配置暴露,导入成功后客户端可能清空安装目录里的 `app_config.json`
5. `Launcher` 确保本机有 `device_id`
6. `Launcher` 使用 `X-Client-Token` 调用更新检查接口。
7. 如果服务端返回可用发布,`Launcher` 启动 `Updater`
8. `Updater` 使用 `X-Client-Token` 拉取 Manifest。
9. `Updater` 校验 Manifest 摘要,并按配置决定是否要求签名。
10. `Updater` 按 Manifest 下载文件。
11. 每个文件下载完成后校验大小和 SHA-256。
12. 安装前校验 staging 目录。
13. 如需替换运行中文件,`Bootstrap` 接管安装。
14. 安装完成后保存 Manifest 缓存和本地状态。
15. 如果主程序开启启动前完整性校验,下次启动时会按本地 Manifest 缓存校验已安装文件。
更新接口使用部署级 `client_token`,不使用客户邮箱密码。客户账号和授权主要控制门户下载、客户权益和席位,不要求最终客户启动软件时再登录。
## 四、当前 SIMCAE 目录规则
客户安装完成后的关键目录是:
| 路径 | 说明 |
| --- | --- |
| `maintenancetool.exe` | Qt IFW 生成的组件维护工具,位于安装根目录 |
| `components.xml` | Qt IFW 记录的已安装组件状态,位于安装根目录 |
| `network.xml` | Qt IFW 记录的组件仓库地址,位于安装根目录 |
| `view/bin/Launcher.exe` | Hub 更新客户端启动入口 |
| `view/bin/Updater.exe` | Hub 整包更新程序 |
| `view/bin/Bootstrap.exe` | Hub 安装接管程序 |
| `view/bin/SimCAE.exe` | SIMCAE 业务主程序 |
| `view/bin/config/app_config.json` | 服务端注入的初始客户配置 |
当前服务端会识别三种运行目录:
| 运行目录 | 服务端写入的 `install_root` | 说明 |
| --- | --- | --- |
| 软件根目录 | `.` | `Launcher` 和主程序就在软件根目录 |
| `bin` | `..` | `Launcher` 在一层 `bin` 目录中 |
| `view/bin` | `../..` | 当前 SIMCAE 标准结构,`Launcher``view/bin` 中 |
`install_root` 不是让客户手动填写的字段。上传发布包或 Qt IFW 交付包时,服务端会根据 `Launcher``Updater``Bootstrap` 的实际位置自动判断。
## 五、服务端注入的配置
正式客户包中的 `app_config.json` 由服务端生成或替换。开发者打 SDK 时不放最终配置,客户也不手动改配置。
服务端生成配置时,信息来源如下:
| 配置内容 | 来源 |
| --- | --- |
| `product_code``app_id` | 管理后台“产品目录”的产品编码 |
| `app_name` | 管理后台“产品目录”的产品名称 |
| `channel` | 管理后台“软件发布”的发布通道 |
| `current_version` | 管理后台“产品版本”的版本号 |
| `platform``arch``abi` | 管理后台“平台管理”和发布包选择的平台 |
| `api_base_url` | 服务端 `.env``SIMCAE_CLIENT_API_BASE_URL` |
| `client_token` | 服务端 `.env``SIMCAE_CLIENT_TOKEN` |
| `launch_token` | 服务端 `.env``SIMCAE_LAUNCH_TOKEN` |
| `install_root` | 服务端根据运行目录自动判断 |
| `main_executable` | 服务端在运行目录中识别到的业务主程序,SIMCAE 当前为 `SimCAE.exe` |
| `launcher_executable` | 按平台生成,Windows 为 `Launcher.exe` |
| `updater_executable` | 按平台生成,Windows 为 `Updater.exe` |
| `bootstrap_executable` | 按平台生成,Windows 为 `Bootstrap.exe` |
| `require_manifest_signature` | 服务端 Manifest 签名配置 |
| `verify_installed_on_start` | 当前服务端默认写入 `false`,需要强制启动校验时再按发布策略开启 |
如果上传包里已经带了旧的 `app_config.json``server_config.json``server_config.qrc``manifest_public_key.pem`,服务端会按当前发布信息重新处理,不让开发机临时配置直接进入最终客户包。
## 六、本地调试配置
正式发布不要手写最终 `app_config.json`。如果开发者只是在本机调试 `Launcher``Updater`,可以创建未提交的 `config/app_config.local.json`
CMake 只在本地输出目录还没有 `config/app_config.json` 时,才会把 `app_config.local.json` 复制成调试用配置。这个文件只服务本机调试,不代表服务端最终注入结果。
`config/server_config.json``config/server_config.qrc` 用于把兜底 API 地址编译进 EXE。正式客户包优先使用服务端注入的 `api_base_url`,一般不需要让客户看到或修改 `server_config.json`
## 七、启动门禁
如果 SIMCAE 主程序开启 `SimCAE_UseLauncher=ON`,用户直接双击 `SimCAE.exe` 会被拦截,必须通过 `Launcher.exe` 启动。
这套机制依赖 `launch_token`
| 位置 | 要求 |
| --- | --- |
| 服务端 `.env` | 必须配置 `SIMCAE_LAUNCH_TOKEN` |
| SIMCAE 编译期 | 主程序编译时使用同一个 token |
| 客户端配置 | 服务端把同一个 token 写入最终客户配置 |
如果三处 token 不一致,就会出现“直接双击被拦住,但从 `Launcher` 启动也失败”的问题。
## 八、Manifest 和哈希校验
整包更新使用 SimCAE Hub Manifest,不使用 Qt IFW 的 `Updates.xml`
Manifest 负责描述:
| 内容 | 说明 |
| --- | --- |
| 发布版本 | 本次更新属于哪个产品、版本线、版本和通道 |
| 文件清单 | 本次发布包含哪些文件 |
| 下载地址 | 每个文件从哪个受控接口下载 |
| 文件大小 | 客户端下载后必须一致 |
| SHA-256 | 客户端下载后必须一致 |
| 是否必选 | 必选文件缺失会阻止启动,可选组件文件可由 MaintenanceTool 管理 |
服务端返回 Manifest 前会重新检查发布包文件是否存在、大小是否一致、SHA-256 是否一致。客户端下载完成后也会再次校验大小和 SHA-256。
## 九、和 MaintenanceTool 的边界
| 能力 | 使用程序 | 文件格式 |
| --- | --- | --- |
| 整包更新 | `Launcher``Updater``Bootstrap` | SimCAE Hub 发布包和 Manifest |
| 组件安装、更新、移除 | `maintenancetool.exe` | Qt IFW repository 和 `Updates.xml` |
两条线可以共存,但不要混淆:
1. `Updater` 不读取 `Updates.xml`
2. `MaintenanceTool` 不读取 SimCAE Hub Manifest。
3. `Updater` 不拉起 `MaintenanceTool`
4. `MaintenanceTool` 由客户手动打开,或由 Qt IFW 自己的流程使用。
5. 核心组件通常包含 `Launcher``Updater``Bootstrap``SimCAE.exe`
6. 可选组件例如 DAP 插件,可以由 MaintenanceTool 单独安装、更新或移除。
## 十、编译环境
| 依赖 | 要求 |
| --- | --- |
| CMake | 建议 3.20 或更高版本 |
| C++ | C++17 |
| Qt | Qt 5,至少需要 Core、Network、Gui、Widgets |
| OpenSSL | 用于 Manifest RSA-SHA256 验签 |
| 编译器 | Windows 推荐 Visual Studio 2022 x64Linux 推荐 gcc/g++ |
项目提供的 CMake Preset
| Preset | 平台 | 用途 |
| --- | --- | --- |
| `x64-debug` | Windows | Debug 编译 |
| `x64-release` | Windows | Release 编译 |
| `linux-x64-debug` | Linux | Debug 编译 |
| `linux-x64-release` | Linux | Release 编译 |
## 十一、Windows 编译
建议安装 Visual Studio 2022、Qt 5 x64、CMake 和 OpenSSL x64。
如果 Qt 没有加入环境变量,可以在编译前指定:
```powershell
$env:CMAKE_PREFIX_PATH = "C:\Qt\5.15.2\msvc2019_64"
```
当前测试机 OpenSSL 路径是 `C:\Program Files\OpenSSL-Win64`Release 编译命令:
```powershell
cmake --preset x64-release -DSIMCAE_OPENSSL_ROOT="C:\Program Files\OpenSSL-Win64"
cmake --build --preset x64-release
```
如果 OpenSSL 安装在其他目录,只改 `SIMCAE_OPENSSL_ROOT` 这一项。
Windows Release 产物通常输出到 `out/bin/Release`
检查核心程序:
```powershell
Test-Path .\out\bin\Release\Launcher.exe
Test-Path .\out\bin\Release\Updater.exe
Test-Path .\out\bin\Release\Bootstrap.exe
```
预期都返回 `True`
## 十二、Linux 编译
Ubuntu 示例:
```bash
sudo apt update
sudo apt install -y build-essential cmake qtbase5-dev qttools5-dev qttools5-dev-tools libssl-dev
cmake --preset linux-x64-release
cmake --build --preset linux-x64-release
```
Linux 下通常直接使用系统 OpenSSL;如果需要指定自定义 OpenSSL,也可以通过 CMake 变量配置。
## 十三、打包 SDK
SDK 打包流程见当前目录 [updater打包成SDK.md](updater打包成SDK.md)。SIMCAE 拿到 SDK 后的安装器、交付包和上传流程见 [SIMCAE打包上传.md](SIMCAE打包上传.md)。
常用输出:
| 输出 | 说明 |
| --- | --- |
| `dist\UpdateClientSDK` | 不带 Qt 运行库的 SDK 展开目录 |
| `dist\UpdateClientSDK.zip` | 不带 Qt 运行库的 SDK 压缩包 |
| `dist\UpdateClientSDK-With-QtDll` | 带 Qt 运行库 DLL 的 SDK 展开目录 |
| `dist\UpdateClientSDK-With-QtDll.zip` | 推荐交给 SIMCAE 开发者的 SDK 压缩包 |
SDK 不包含最终客户配置。`With-QtDll` 表示包里带的是运行所需的 Qt DLL,不是完整 Qt SDK。SDK 的目标是给 SIMCAE 打包流程提供更新客户端程序和运行库。
## 十四、运行数据位置
Windows 运行配置会导入当前用户配置,按安装运行目录计算 installation id。运行数据目录通常位于:
`%LOCALAPPDATA%\SimCAE\HubUpdateClient\installations\<安装目录SHA256>\`
Linux 运行数据目录通常位于:
`$XDG_DATA_HOME/SimCAE/HubUpdateClient/installations/<安装目录SHA256>/`
未设置 `XDG_DATA_HOME` 时通常是:
`~/.local/share/SimCAE/HubUpdateClient/installations/<安装目录SHA256>/`
Manifest 缓存保存在运行数据目录下的 `update/manifest_cache`
## 十五、常见问题
| 现象 | 排查方向 |
| --- | --- |
| 客户启动后提示配置不完整 | 检查交付包是否经过 SimCAE Hub 上传注入,不要直接拿本地未注入包给客户 |
| 检查更新没有结果 | 检查后台发布是否已发布、发布包是否可用、产品编码、通道和平台是否一致 |
| 下载返回 401 | 检查客户包里的 `client_token` 是否来自当前服务端 `.env` |
| Manifest 校验失败 | 检查服务端文件是否被手工改过,大小和 SHA-256 是否与数据库一致 |
| 强制签名失败 | 检查 `manifest_public_key.pem` 与服务端私钥是否匹配 |
| 主程序启动失败 | 检查 `main_executable` 和运行目录是否正确 |
| 从 `Launcher` 启动也被拦截 | 检查服务端、SIMCAE 编译期和客户配置中的 `launch_token` 是否一致 |
| MaintenanceTool 看不到组件更新 | 检查 IFW repository 地址、`Updates.xml` 和组件版本是否正确 |