# UpdateClientSDK 客户端部署说明 本文按“维护者打包 SDK -> 你接入业务软件 -> 联调测试 -> 生成最终客户端包”的顺序说明。你拿到这份文档后,按章节一步一步做即可。 ## 一、这个 SDK 是什么 UpdateClientSDK 是“独立更新器 SDK / 升级运行时 SDK”。它不是传统的 `include + lib` 形态,而是把自动升级能力做成一组独立程序,让业务软件通过这些程序完成检查更新、下载、安装、回滚和启动保护。 SDK 核心程序: - `Launcher.exe`:用户入口。检查版本、验证授权和策略,决定直接启动业务主程序或进入升级流程。 - `Updater.exe`:下载、校验、备份、安装、健康确认、提交或回滚。 - `Bootstrap.exe`:处理运行中可能被占用的 EXE/DLL 替换。 - `config/app_config.json`:部署配置源文件。启动时会同步到当前 Windows 用户的注册表,运行时优先读注册表。 - `config/manifest_public_key.pem`:Manifest 签名公钥,用来验证服务端发布包没有被篡改。 ## 二、维护者:生成 SDK 包 这一节是 SDK 维护者操作。接入方通常只需要拿到 `UpdateClientSDK.zip`。 打包前确认: 1. 已在 Windows 上用 Release 配置编译完成,输出目录里有 `Launcher.exe`、`Updater.exe`、`Bootstrap.exe`。 2. `config/manifest_public_key.pem` 和服务端使用的私钥是一对。 3. SDK Word 接入说明已经放在 `update-client` 根目录或 `update-client/Docs` 目录下,文件名包含 `SDK`,例如 `SimCAE自动升级SDK接入说明_v0.1.docx`。打包脚本会把它复制到 SDK 根目录,方便接入方一打开压缩包就能看到。 4. 如果业务软件本身已经带 Qt DLL,通常不要把 SDK 的 Qt 运行库打进去,避免 Qt 版本混用。 在 Windows PowerShell 中执行: ```powershell cd C:\Users\admin\Desktop\update-client .\scripts\package-sdk.ps1 ` -SourceDir .\out\bin ` -OutputDir .\dist\UpdateClientSDK ` -ZipFile .\dist\UpdateClientSDK.zip ` -SdkVersion 0.1.0 ``` 生成结果: ```text dist/ UpdateClientSDK/ SimCAE自动升级SDK接入说明_v0.1.docx sdk_manifest.json bin/ Launcher.exe Updater.exe Bootstrap.exe ... config/ app_config.json manifest_public_key.pem scripts/ install-sdk.ps1 package-client.ps1 package-sdk.ps1 UpdateClientSDK.zip ``` 把 `dist/UpdateClientSDK.zip` 发给接入方即可。 可选参数: - `-IncludeDemoMainApp`:把仓库里的 Demo 主程序 `MainApp.exe` 也打进 SDK,方便演示。 - `-IncludeQtRuntime`:把 Qt 运行库也打进 SDK。只有业务软件本身不带 Qt 时才建议使用。 ## 三、你:把 SDK 放进业务软件目录 假设业务软件目录是: ```text D:\SimCAE\ bin\ SimCAE.exe Qt5Core.dll ... Licenses\ installerResources\ ``` 推荐把 SDK 放到 `bin` 目录,和 `SimCAE.exe` 同级;后台发布新版本时仍选择整个 `D:\SimCAE\` 作为发布根目录。 先解压 SDK: ```powershell Expand-Archive D:\交付\UpdateClientSDK.zip -DestinationPath D:\SimCAE_SDK -Force ``` 再安装到业务软件的 `bin` 目录: ```powershell cd D:\SimCAE\bin D:\SimCAE_SDK\scripts\install-sdk.ps1 ` -SdkRoot D:\SimCAE_SDK ` -ReleaseDir . ``` 安装后目录应类似: ```text D:\SimCAE\ bin\ Launcher.exe Updater.exe Bootstrap.exe SimCAE.exe config\ app_config.json manifest_public_key.pem Qt5Core.dll ... Licenses\ installerResources\ ``` 如果你需要重新覆盖 `config/app_config.json`,执行安装脚本时加 `-OverwriteConfig`: ```powershell D:\SimCAE_SDK\scripts\install-sdk.ps1 ` -SdkRoot D:\SimCAE_SDK ` -ReleaseDir D:\SimCAE\bin ` -OverwriteConfig ``` 注意:SimCAE 自己已经带有 Qt 运行库。SDK 的 Launcher/Updater 应复用 SimCAE 的 `Qt5*.dll`、`platforms/`、`imageformats/` 等目录。不要把另一套 Qt DLL 覆盖到 `SimCAE\bin`,否则可能出现“无法定位程序输入点”一类错误。 ## 四、你:生成并填写 app_config.json 最推荐的方式是在服务端管理后台生成客户端配置: 1. 浏览器打开服务端管理后台,例如 `http://服务器IP:8000/`。 2. 登录后台。 3. 创建或选择应用,例如 `app_id=simcae`。 4. 创建 License。 5. 在“客户端配置生成”区域选择应用、渠道、License 和主程序名。 6. 点击生成配置。 7. 复制生成的 JSON,覆盖 `D:\SimCAE\bin\config\app_config.json`。 配置同步规则: - `app_config.json` 是部署配置源文件,适合交付、复制、人工修改。 - Launcher / Updater / MainApp 启动时会计算 `app_config.json` 解析后的 JSON 内容 SHA256;如果 JSON 内容和上次导入时不同,就把文件里的配置重新写入当前 Windows 用户的注册表。 - 后续运行时优先从注册表读取配置,不再每次直接读 JSON。 - 运行过程中产生的动态值,例如首次输入的 `license_key`、服务端返回的 `device_id`、升级后的 `current_version`,会写入注册表。 - 如果你手动修改了 `app_config.json`,下一次启动会重新导入并覆盖注册表里的同名字段。 - 如果检测到 `app_config.json` 确实发生变化,SDK 会同时删除 `config/client_identity.dat` 和 `config/version_policy.dat`,避免继续使用旧 License、旧设备身份或旧版本策略;如果安装目录不可写,会弹出管理员权限确认框。 - 注册表按安装目录隔离;同一台电脑上多个安装目录不会互相覆盖配置。 - 注册表位置为 `HKEY_CURRENT_USER\Software\Marsco\UpdateClientSDK\installations\<安装目录SHA256>\config`。 关键字段说明: - `app_id`:服务端应用 ID,要和管理后台里的应用一致。 - `app_name`:应用显示名称。 - `channel`:发布渠道,例如 `stable`、`beta`、`dev`。 - `current_version`:客户端当前初始版本,必须和后台已发布的版本一致。 - `client_protocol`:客户端协议号,当前建议为 `3`。 - `launch_token`:本机启动票据 HMAC 密钥。服务端生成配置时会填默认值;正式部署建议按项目统一修改。 - `license_key`:管理后台创建 License 后生成的授权码。为空时首次启动 `Launcher.exe` 会弹窗让用户输入并保存到注册表;如果授权错误或过期,也会提示重新输入。 - `api_base_url`:服务端 API 地址,例如 `http://192.168.229.128:8000`。 - `client_token`:服务端 `.env` 中的 `CLIENT_API_TOKEN`,必须和服务端一致。 - `device_id`:设备 ID。一般可以留空,首次启动时 SDK 会向服务端登记并写入注册表。 - `install_root`:被更新的安装根目录相对 `Launcher.exe` 所在目录的位置。SDK 放在 `bin` 时填 `..`。 - `main_executable`:业务主程序相对 `Launcher.exe` 所在目录的路径。SDK 放在 `bin` 且主程序也在 `bin` 时填 `SimCAE.exe`。 - `launcher_executable`、`updater_executable`、`bootstrap_executable`:通常不用改。 - `platform`、`arch`:当前为 `windows`、`x64`。 典型配置: ```json { "app_id": "simcae", "app_name": "SimCAE", "channel": "stable", "current_version": "1.0.0", "client_protocol": "3", "launch_token": "SimCAE_Launch_Token_2026_ChangeMe_32Bytes", "license_key": "MARSCO-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "api_base_url": "http://192.168.229.128:8000", "client_token": "SimCAEClientToken2026", "request_timeout_ms": "5000", "temp_folder": "update_temp", "device_id": "", "install_root": "..", "main_executable": "SimCAE.exe", "launcher_executable": "Launcher.exe", "updater_executable": "Updater.exe", "bootstrap_executable": "Bootstrap.exe", "health_check_timeout_ms": "15000", "platform": "windows", "arch": "x64" } ``` ## 五、你:业务主程序需要配合什么 当前安全模式下,业务主程序需要配合两件事: 1. 接收 `--ticket-file=` 参数,验证并消费一次性启动票据。 2. 如果收到 `--health-file=` 参数,启动成功后向该路径写入 `ok\n`,让 Updater 确认新版本可用。 接入位置: ```text main / WinMain 开头,创建主窗口之前 ``` 当前仓库里的 `update-client/MainApp/main.cpp` 是接入示例,已经实现: - 启动票据校验。 - 本地 License/设备身份校验。 - 本地策略校验。 - Manifest 完整性校验。 - 健康标记写入。 真正接入业务软件时,把这些启动检查逻辑移植到业务主程序。用户入口应改成 `Launcher.exe`,不要让用户直接双击 `SimCAE.exe`。 ## 六、你:准备服务端数据 首次联调前,服务端至少要准备这些内容: 1. 创建应用,例如 `simcae`。 2. 创建渠道,例如 `stable`。 3. 创建 License。 4. 发布一个初始版本,例如 `1.0.0`。 5. 生成客户端配置,并写入 `bin\config\app_config.json`。客户端下次启动时会自动同步到注册表。 为什么必须先发布初始版本:Launcher 启动业务主程序前会做 Manifest 完整性校验。这个 Manifest 是服务端发布版本时生成并签名的清单,用来证明当前本地文件属于一个可信版本。如果没有发布过 `current_version` 对应版本,客户端会提示签名 Manifest 缓存缺失。 后台发布版本时,选择整个安装根目录,例如 `D:\SimCAE\`,不要只选择 `D:\SimCAE\bin`。这样服务端会把 `bin/SimCAE.exe`、`Licenses/`、`installerResources/` 等完整结构写进 Manifest。 ## 七、你:运行和联调 基础联调步骤: 1. 确认服务端正在运行。 2. 确认 `bin\config\app_config.json` 中 `api_base_url`、`client_token`、`license_key`、`current_version` 正确。 3. 双击 `bin\Launcher.exe`。 4. 首次启动时如果 `license_key` 为空,按弹窗输入后台创建的 License;SDK 会把它保存到注册表。 5. 成功进入业务主程序后,回到后台查看设备、升级日志、下载日志。 6. 在后台发布更高版本,例如从 `1.0.0` 发布到 `1.0.1`。 7. 再次启动 `Launcher.exe`,验证升级、健康确认和回滚逻辑。 联调目录建议: ```text D:\SimCAE_Release\ C:\Users\<你的用户名>\Desktop\SimCAE_Release\ ``` 如果安装在 `C:\Program Files\...` 这类默认不可写目录,普通配置值会写入当前用户注册表,不需要修改 `app_config.json`。但 `client_identity.dat`、`local_state.json`、`version_policy.dat` 等本地状态文件仍位于安装目录下;当这些文件需要写入且目录不可写时,SDK 会弹出 Windows 管理员权限确认框,用户点击“是”后会继续保存。 注意:这次提权主要覆盖小型配置/状态文件的写入和删除。更新缓存、离线包暂存、升级替换 EXE/DLL 等大文件操作仍建议放在可写目录;如果最终产品必须完整安装到 `C:\Program Files\SimCAE\bin` 并在普通用户下自动升级,后续建议把运行时状态迁移到 `ProgramData` / `AppData`,或让 Updater/Bootstrap 在替换安装目录文件时走管理员权限。 ## 八、维护者:生成某个产品的最终客户端包 SDK 是给接入方开发使用的。最终给用户安装或分发时,可以从已经联调过的 Release 目录生成最终客户端包。 在 Windows PowerShell 中执行: ```powershell cd C:\Users\admin\Desktop\update-client .\scripts\package-client.ps1 ` -SourceDir .\out\bin ` -ConfigFile .\config\app_config.json ` -OutputDir .\dist\UpdateClient ` -ZipFile .\dist\UpdateClient.zip ``` `package-client.ps1` 会检查: - 配置文件必填字段是否完整。 - 主程序、Launcher、Updater、Bootstrap 是否存在。 - 是否混入 Debug DLL、PDB、ILK。 - 当前版本是否已有签名 Manifest 缓存。 - 是否存在重复主程序。 生成结果: ```text dist/ UpdateClient/ UpdateClient.zip ``` ## 九、常见错误 1. 直接启动业务主程序提示 ticket 错误:应从 `Launcher.exe` 启动。 2. 首次启动保存配置/状态文件失败:如果目录不可写,SDK 会弹出管理员权限确认框;用户取消或当前账号没有管理员权限时仍会失败。 3. 首次启动设备登记失败:检查 `api_base_url`、`client_token`、`license_key`、服务端 License 状态。 4. 提示 License 错误或过期:在后台确认 License 是否存在、是否被禁用或删除、是否超过最大设备数。 5. 策略或 Manifest 验签失败:检查 `config/manifest_public_key.pem` 是否和服务端私钥匹配。 6. 提示 signed manifest cache missing:先在后台发布一次 `current_version` 对应版本,并让客户端拿到该版本 Manifest。 7. 升级后回滚:检查业务程序是否在 `health_check_timeout_ms` 内写入健康标记。 8. 发布失败提示主程序不在根目录:服务端 `.env` 中 `RELEASE_MAIN_EXECUTABLE` 默认是 `bin/SimCAE.exe`,发布目录要选择包含 `bin/SimCAE.exe` 的安装根目录。 9. 启动时提示 `无法定位程序输入点 ... Qt5*.dll`:通常是 Qt DLL 被不同版本覆盖或混用。恢复业务软件原始 Qt DLL,并重新打包 SDK;SimCAE 场景下不要使用 `-IncludeQtRuntime`。