用途
本技能用于分发通过自签名证书签名的 Windows MSIX 应用包(MSIX 是 Windows 的现代应用包格式),且不依赖在线托管更新站点。它要解决的问题是:打包工具通常只产出三类内容——MSIX 安装包、一个小的可执行包装器和一个应用安装器清单;后两者是在线运行的,会访问配置的站点基础 URL(通常是“最新版本”路径)。在发布版本存在之前(例如所有预发布构建、从 CI 下载的产物),这些 URL 返回 404,二者都会失败;而仅凭 MSIX 安装包也无法直接双击安装,因为本机不信任生成它的自签名证书。
主要能力
- 离线安装包结构:一个 zip 压缩包,内含三个文件:
install.bat:提权到管理员 → 导入证书 → 旁加载安装包app.crt:自签名代码签名证书app-<version>.x64.msix:应用包本身
- CI 自动组装:从打包工具输出目录收集文件并打成 zip,示例流程包括:检查
output/app.crt是否存在(缺失则报错退出),用 glob 找到output/app-*.x64.msix,复制install.bat、证书和 msix 到临时目录后压缩为App-Windows-installer.zip。 - 安装脚本要点:提权(通过
Start-Process -Verb RunAs重新启动脚本)、将证书导入本机受信任人存储(certutil -addstore -f "TrustedPeople" app.crt,幂等可重复执行)、用Add-AppxPackage配合-ForceApplicationShutdown -ForceUpdateFromAnyVersion安装,失败时回退到先卸载再安装,并打印恢复步骤。
使用方式与关键陷阱
- 确保证书存在:签名步骤可能失败而构建其余部分成功,导致 zip 缺文件;CI 中必须断言证书存在并让任务失败。
- 导入到本机存储:目标应为机器的 TrustedPeople 存储而非当前用户存储,且该命令幂等,重复运行安全。
- 自提权:证书导入和旁加载都需要管理员权限,通过
net session检测并重新以 RunAs 启动,保持双击即可完成。 - 签名密钥稳定:包发布者身份由签名证书决定;重新生成密钥会使现有安装变成另一个应用,原地更新失败,只能先卸载旧包(有数据丢失风险)。应将密钥固定为 CI secret,不要随意轮换。
- 强制更新与回退:不加
-ForceUpdateFromAnyVersion时,同版本号重建不会覆盖已有安装;即使加上,安装仍可能失败(常见原因是发布者变更),需捕获失败并回退到先卸载再安装。 - 注意 cmd 续行规则:双引号字符串内的
^不会续行,带引号的命令必须保持在一个物理行;只有-Command后、引号外的^合法。 - 用 glob 匹配包名:文件名带版本号,硬编码需要每次发布修改;用
for %%f in ("%~dp0app-*.msix") do set "MSIX=%%f"可跨版本复用。 - 切换工作目录:脚本运行目录未必是用户解压目录,先
cd /d "%~dp0",并用%~dp0引用捆绑文件。 - 失败时打印恢复步骤:常见两类失败是开发者设置中旁加载被禁用,以及机器需要重启后才能让新信任的证书生效。
- 说明卸载方式:旁加载的包不在用户寻找安装器的位置,应告知用户可在“已安装的应用”中找到。
适用场景
- 内测、预发布版本的离线分发
- 从 CI 构建产物直接分发给测试者
- 无法访问在线更新站点的环境
限制与验证
- 证书必须由构建实际产出并经过签名,否则包不可安装。
- 签名密钥若轮换,已有安装的升级路径会中断。
- 验证应在从未构建过该应用的机器上解压并双击脚本,因为开发者机器已信任证书,无法复现不信任场景。
- 在任务管理器详细信息中确认应用实际启动的架构,因为包可能以模拟方式运行而不提示。
- 除全新安装外,还应测试升级路径:先安装上一版本,再用新包覆盖安装。