PowerToys 本地 winget 安装测试实战:构建、哈希、自托管与清单验证全流程
Microsoft PowerToys 每次发版前,都需要在 microsoft/winget-pkgs 清单仓库提交 winget 清单(manifest),而清单中的下载链接与 SHA256 哈希在提交前是无法直接对线上 Release 做端到端验证的。官方开发文档 test-winget-install-locally.md 为此提供了一套完整流程:本地构建或取回安装程序 → 计算哈希 → 自托管安装包 → 修改本地清单 → 用 winget install --manifest 走真实安装链路。读完本篇,你将掌握如何用 winget 的本地清单(Local Manifest)机制,在不污染线上发布的情况下验证 PowerToys 的 winget 安装场景是否可用。
为什么需要本地测试 winget 安装
PowerToys 的 winget 清单定义在独立的 winget 清单仓库中(对应 manifests/m/Microsoft/PowerToys 路径,包标识为 Microsoft.PowerToys),每个版本一个目录,目录内包含 3 个 yml 文件。由于清单提交前需要保证:
InstallerUrl指向的安装包可正常下载;Sha256与安装包逐字节匹配;winget install能完整拉起 WiX Bootstrapper 并完成安装;
因此开发者会在本地搭建一个“模拟发布环境”:用自建端点托管安装程序,再用 winget 的 --manifest 参数直接指定本地清单文件夹安装。这套机制不依赖清单是否已合入官方仓库,是发布前验证的标准手段。
第一步:获取安装程序产物
文档给出两条获取途径:
- 从发布 CI 管线取产物:在 “Pipelines - Runs for PowerToys Signed YAML Release Build” 流水线中获取发布产物;
- 本地自行构建:执行
tools\build\build-installer.ps1脚本。
本地构建脚本 build-installer.ps1 是完整的本地打包管线(restore、构建、MSIX 签名、WiX v5 MSI/Bootstrapper 生成),其参数定义如下(见 build-installer.ps1):
| 参数 | 默认值 | 说明 |
|---|---|---|
-Platform |
x64(未指定时自动检测) |
目标平台,x64 / arm64 |
-Configuration |
Release |
构建配置,Release / Debug |
-PerUser |
true |
true 构建 per-user 安装程序,false 构建 machine-wide 安装程序 |
-Version |
取自 src/Version.props 中的 Version 属性(当前为 0.0.1) |
显式指定 PowerToys 版本号,内部通过 versionSetting.ps1 写入 |
-Force |
— | 工作区不干净时跳过交互提示继续构建 |
-Clean |
— | 构建前清理 bin/obj 与 MSBuild 输出 |
-SkipBuild |
— | 跳过主解决方案构建(假定已构建过) |
-EnableCmdPalAOT |
— | 启用 CmdPal 的 AOT 编译(构建更慢) |
脚本的典型调用方式(见 BUILD-GUIDELINES.md):
.\tools\build\build-installer.ps1 -Platform x64 -Configuration Release -PerUser true
构建完成后,安装程序按脚本注释(见 build-installer.ps1)输出到相对于仓库根目录的路径:
installer/PowerToysSetupVNext/<Platform>/<Configuration>/UserSetup # -PerUser true
installer/PowerToysSetupVNext/<Platform>/<Configuration>/MachineSetup # -PerUser false
这里与 winget 清单中的安装作用域(--scope user 还是 --scope machine)直接对应。从 doc/devdocs/core/installer.md 可知,两种安装方式功能完全一致,差异仅在于:
- Per-User:安装到
%LOCALAPPDATA%\PowerToys,注册表写入HKCU,不同用户可各自持有独立安装;当前默认即 Per-User; - Per-Machine:安装到
Program Files\PowerToys,注册表写入HKLM,全机共享一份安装。
因此,若要测试 --scope user 安装,应使用默认 -PerUser true 构建出的 UserSetup 目录中的 Bootstrapper .exe;若要测试 machine 作用域,则需 -PerUser false 重新构建 MachineSetup 产物。
注意:首次在本机构建安装程序时,建议以管理员身份运行构建流程,以便 WiX 工具将
wix.target移动到指定位置并信任用于签名 MSIX 包的证书(见 doc/devdocs/core/installer.md)。由于本地构建的 MSIX 使用本地开发证书签名,若要在其他机器上运行该安装程序,需先用 cert-management.ps1 导出签名证书并在目标机器上信任(见 build-installer.ps1 的 NOTES 说明)。
第二步:计算安装程序的 SHA256 哈希
winget 清单强制要求安装包哈希,winget 在下载后会校验,不匹配即拒绝安装。文档给出的计算方式为:
cd /path/to/your/directory/contains/installer
Get-FileHash -Path ".\<Installer-name>.exe" -Algorithm SHA256
将 <Installer-name>.exe 替换为第一步产物目录中实际的 Bootstrapper 文件名,Get-FileHash 输出的 Hash 值(64 位十六进制串)就是要写入清单 Sha256 字段的值。注意哈希必须针对最终托管出去的那一份文件计算,任何重新打包、重签名都会使其失效。
第三步:托管安装程序(Self-Host)
文档特别强调一条限制:不能直接使用 staged 的 GitHub Release 产物或发布管线中的产物(原文:Attention: staged github release artifacts or artifacts in release pipeline is not OK in this step),必须提供一个可公开访问的下载端点。
文档推荐的最简自托管方式是 Python 内置 HTTP 服务:
python -m http.server 8000
在仓库根目录(或产物目录)执行后,安装程序的下载地址形如 http://<本机IP>:8000/installer/PowerToysSetupVNext/x64/Release/UserSetup/<Installer-name>.exe,该 URL 将作为清单中的 InstallerUrl。实测时还需要注意:
python -m http.server是单线程简单服务,仅供本机/局域网验证使用,不要用于任何生产场景;- 若从其他机器测试,需放行 Windows 防火墙的 8000 端口入站;
- 服务进程存活期间不要移动或修改产物目录,否则下载到的文件与哈希计算时的文件不一致,winget 校验将失败。
第四步:准备本地清单文件夹
从 winget 清单仓库下载一个已发布的版本目录(文档以 PowerToys 0.92.1 版本目录为例),该目录包含 3 个 yml 文件。
文档原文提醒:Do not put any files other than these three in this folder —— 该文件夹内除这 3 个 yml 文件外不得放任何其他文件,否则 winget 在解析本地清单时会报错。
这 3 个文件是 winget 清单的标准组成:版本清单(声明包标识、版本、发行信息等)、本地化清单(显示名称、发布者等本地化字段)与安装程序清单(声明 InstallerUrl、Sha256、架构与作用域)。本地测试中只需改动其中的版本相关字段与安装程序字段,不需要改动包标识。
第五步:修改清单的版本、URL 与哈希
针对你的测试场景,对 3 个 yml 文件做如下修改:
- 版本号:将 3 个文件中的版本字段统一改为与你的安装程序一致的版本(清单内版本字段需保持一致;若该版本号在本地机器已装过 winget 包,winget 可能提示版本不更高,此时可用更高的测试版本号);
InstallerUrl:替换为第三步自托管端点的完整 URL;Sha256:替换为第二步计算出的哈希值。
版本与清单中声明的架构/作用域也需与产物匹配:清单若声明 x64 + user scope,就应使用 -Platform x64 -PerUser true 构建的 UserSetup 产物。
第六步:执行 winget 本地清单安装
文档给出的安装命令(需以管理员身份运行):
#execute as admin
winget settings --enable LocalManifestFiles
winget install --manifest "<folder_path_of_manifest_files>" --architecture x64 --scope user
各参数含义:
winget settings --enable LocalManifestFiles:开启“允许本地清单文件”开关,这是--manifest生效的前提;该设置是机器级配置,测试完成后建议用winget settings --disable LocalManifestFiles关闭;--manifest "<folder_path_of_manifest_files>":指向第四步准备的、只含 3 个 yml 的清单文件夹;--architecture x64:与清单声明及安装程序架构一致;arm64 机器上构建并使用 arm64 产物时改为对应值;--scope user:以 per-user 作用域安装(产物需为UserSetup);machine 作用域测试则改为--scope machine(产物需为MachineSetup,且安装过程需要管理员凭据)。
安装过程即真实复现了用户侧的 winget 安装链路:winget 解析清单 → 从 InstallerUrl 下载 → 校验 SHA256 → 拉起 WiX Bootstrapper(依赖检查、关闭已有 PowerToys)→ 安装 MSI → 注册组件。
验证与排错
安装完成后可按以下路径确认结果:
- 安装目录:per-user 安装位于
%LOCALAPPDATA%\PowerToys,per-machine 位于Program Files\PowerToys(见 doc/devdocs/core/installer.md); - 安装日志:Bootstrapper/MSI 日志位于
%LOCALAPPDATA%\Temp\PowerToys_bootstrapper_*.log,自定义安装动作日志位于%LOCALAPPDATA%\Temp\PowerToys_*.log,是定位安装失败的首要依据(见 doc/devdocs/core/installer.md); - 包状态:
winget list --id Microsoft.PowerToys查看 winget 视角的安装状态;验证完毕可用winget uninstall --id Microsoft.PowerToys清理环境。
结合构建侧脚本还能解释几类常见失败:
- 哈希不匹配:通常源于托管文件与计算哈希的文件不是同一份,或自托管目录在托管过程中被重新构建(
build-installer.ps1在构建前会清理installer/下部分输出,见 BUILD-GUIDELINES.md),重新计算哈希即可; - 构建日志:构建阶段失败时查看解决方案/项目旁的
build.<configuration>.<platform>.errors.log等日志文件(见 BUILD-GUIDELINES.md); - 作用域与产物不匹配:用
--scope machine安装了UserSetup产物(或反之)会因清单声明与 Bootstrapper 类型不一致而失败,需重新构建对应-PerUser值的产物。
小结
这套本地 winget 安装测试流程覆盖了从产物生成到清单验证的完整链路:
- 用 build-installer.ps1 本地构建(或从发布管线获取)安装程序产物;
Get-FileHash -Algorithm SHA256计算产物哈希;- 用
python -m http.server 8000等自托管端点暴露产物,避免使用管线/Release 暂存产物; - 取一份官方版本清单目录(严格保持 3 个 yml 文件);
- 修改版本、
InstallerUrl与Sha256; - 管理员下
winget settings --enable LocalManifestFiles+winget install --manifest ... --architecture x64 --scope user完成真实链路验证。
掌握该流程后,任何涉及 winget 清单变更(URL、哈希、作用域、架构)的 PowerToys 发版动作,都可以在合入清单仓库前完成端到端验证,把安装失败问题拦截在发布之前。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00