PowerToys 开发规范全解:依赖许可、代码签名、性能测量与测试要求
【免费下载链接】PowerToysMicrosoft PowerToys is a collection of utilities that supercharge productivity and customization on Windows项目地址: https://gitcode.com/GitHub_Trending/po/PowerToys
本文基于 PowerToys 仓库中的官方开发指南 doc/devdocs/development/guidelines.md 展开,系统讲解 Microsoft PowerToys 对第三方依赖引入、代码签名、性能测量、依赖升级、测试要求以及 PR 与发布流程的全部规范。读完本文,你将理解一个新模块从引入外部库到进入发布签核的完整约束链路,并能在仓库中找到每条规范对应的实现与配置证据。
一、开源包与第三方库的引入规范
PowerToys 对引入开源依赖有明确的许可与安全双重门槛,这是该仓库开发规范中最基础的部分。
许可证要求
- MIT 许可通常可以被接受,可以直接引入项目;
- 任何非 MIT 许可的包,都必须先与 PM(产品管理)团队二次确认;
- 所有外部包或项目都必须在 NOTICE.md 中登记。当前仓库的 NOTICE.md 已按模块逐一列出第三方来源与完整许可证文本,例如 Color Picker 模块引用的 Martin Chrzan's Color Picker(MIT License)就在其中完整披露,共覆盖 Color Picker、Command Palette、ImageResizer、PowerToys Run、Installer/Runner、Peek 等十余个模块的第三方材料;
- 即使某许可本身允许自由使用,规范仍建议与团队确认后再引入。
安全与质量要求
规范特别强调引入代码前必须评估其安全性,原因直指 PowerToys 的发布流水线:流水线会用微软证书对外部 DLL 进行签名。一条具体而重要的推论是——如果引入了不安全或质量不佳的代码,它同样会被微软证书签名,一旦出问题造成的影响会被放大。因此规范给出三条实操准则:
- 确保所引入的代码本身是安全可用的;
- 避免使用使用面很窄、不流行的仓库或包;
- 优先选择下载量/使用量大、口碑评分好的包。
这一"签名放大风险"的视角,是理解 PowerToys 后续代码签名规范的背景。
二、代码签名:所有 DLL 与可执行文件必须签名
签名 JSON 文件的维护方式
签名清单(signing JSON 文件)的修改通常是手工进行的,触发场景有两类:
- 新增 DLL 时:无论是 PowerToys 内部模块产生的 DLL,还是外部引入的库;
- 发布流水线报错时:当流水线以"未签名 DLL/可执行文件列表"失败时——
- 若是 PowerToys 自身的 DLL,直接手动将其加入签名列表;
- 若是外部 DLL,必须先验证其安全可签名,再纳入清单。
文件签名的硬性要求
- 所有 DLL 和可执行文件都必须签名,没有例外;
- 新增文件必须补充进签名配置;
- CI 会检查所有文件是否已签名,未签名文件会导致流水线失败;
- 即使是微软自身提供的依赖,如果它尚未签名,也会被纳入签名流程。
从仓库结构看,模块以独立 DLL 动态加载的方式集成(见下文性能测量部分),模块产物 DLL 数量众多,这使得"新增 DLL 必须同步更新签名清单"成为发布过程中高频、必须遵守的操作。
三、性能测量:Stopwatch、日志与模块加载开销
开发指南对性能测量给出了坦率的现状描述,这部分内容对理解 PowerToys 启动行为很有价值。
现状:没有内建启动计时器
- 当前仓库没有内建的定时器来度量 PowerToys 的启动时间;
- 指南提出可改进的方案:在 runner 的
main方法开始处、以及所有模块接口 DLL 加载完成之后各埋一个测量点; - 替代手段是直接使用性能分析器(Profiler)或 Visual Studio 内置的 Profiler;
- 目前没有专门的性能仪表盘或专用测量工具。
启动耗时来自哪里:约 20 个模块接口 DLL
指南指出启动当前需要一定时间,原因是:
- 大约20 个模块接口 DLL需要被逐一加载;
- 部分模块在加载阶段即被启动。
这一点可以从 runner 的源码得到印证:powertoy_module.cpp 中的load_powertoy函数对每个模块执行LoadLibraryW(filename)动态加载接口 DLL,随后通过GetProcAddress取出导出符号powertoy_create来构造模块实例。每个模块都走一次 Win32 动态库加载路径,这正是"约 20 个模块接口 DLL"造成启动开销的直接机制。
现有的性能数据获取方式
- 代码中使用
System.Diagnostics.Stopwatch进行计时,仓库中大量模块(如 PowerLauncher、Command Palette、Settings.UI、Peek 等)都可直接检索到Stopwatch的使用; - 性能数据写入 PowerToys 的默认日志,排查性能问题时可以按日志中的 stopwatch 相关消息进行检索定位;
- 部分遥测事件也携带性能信息,可作为辅助数据源。
四、依赖管理:WinRT SDK、CsWinRT 与 WebView2
WinRT SDK 与 CsWinRT 的周期性升级
- WinRT SDK 与 CsWinRT 的更新是周期性进行的;
- 两者版本相互牵制:WinRT SDK 往往要求更高版本的 CsWinRT,反之亦然;
- 新版本可在 NuGet.org 或 Visual Studio 的 NuGet Package Explorer 中查看;
- 稳定版优先于预览版;
- 最佳实践是在发布周期早期就升级,以便尽早暴露可能的回归。
仓库的 Directory.Packages.props 中可以看到这条规范的直接体现:
<PackageVersion Include="Microsoft.Windows.CppWinRT" Version="2.0.250303.1" /> <PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.4022.49" /> <!-- CsWinRT version needs to be set to have a WinRT.Runtime.dll at the same version contained inside the NET SDK we're currently building on CI. --> <PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />注释明确写出:CsWinRT 的版本必须与 CI 构建所用 .NET SDK 内置的WinRT.Runtime.dll版本保持一致——这正是文档所述"WinRT SDK 与 CsWinRT 相互牵制"在仓库中的具体落地,说明升级时不能孤立地只改其中一个版本。
WebView2
- WebView2 用于 Monacoo/Monaco 文件预览等组件(见 src/Monaco 的 Monaco 编辑器集成);
- WebView2 SDK 的版本与Windows 中的 WebView 运行时相关联。历史上曾因 Windows Update 安装新版 WebView 运行时引发问题,现在 WebView 团队已将 PowerToys 的测试纳入其发布周期;
- 升级 WebView2 的固定流程:
- 更新版本号;
- 提交 PR;
- 对所有使用 WebView2 的组件做 sanity check(正常性验证)。
通用依赖更新流程
- 通过 Visual Studio 更新时,依赖会被自动联动更新;
- 更新完成后必须执行三步:
- Clean build(干净构建);
- Sanity check 确认所有模块仍然正常工作;
- 提交包含变更的 PR。
五、测试要求:多机、多屏与 Fuzzing
Mouse Without Borders 需要多台物理计算机
- 该模块必须使用多台物理计算机才能正确测试;
- 不建议用虚拟机测试,因为宿主与来宾之间的鼠标输入容易造成混淆;
- 至少需要 2 台计算机,有时会用到 3 台;
- 测试通常指派给已知拥有多台计算机的团队成员。
多显示器要求
- 部分工具(如 FancyZones、鼠标类模块)需要多显示器环境测试;
- 建议至少 2 台显示器;
- 其中一台应能使用不同的 DPI 设置,以覆盖混合 DPI 场景。
Fuzzing 测试:安全团队的硬性要求
- 对处理文件 I/O 或用户输入的模块,安全团队要求必须做 fuzzing 测试;
- Fuzzing 通过向程序投喂随机、非法或意料之外的数据来发现漏洞与缺陷;
- PowerToys 集成了微软的OneFuzz 服务做自动化测试;
- .NET(C#)与 C++ 模块采用不同的 fuzzing 实现路径(.NET 走 OneFuzz 的 .NET fuzzer,C++ 走 libFuzzer);
- 新模块若处理文件 I/O 或用户输入,应当实现 fuzzing 测试;
- 详细配置(包括
OneFuzzConfig.json的字段说明与示例)见仓库内专文 Fuzzing Testing in PowerToys。
发布候选(RC)测试中的 Bug 处理流程
在 release candidate 测试阶段报告 bug 时,遵循固定的五步流程:
- 在团队聊天中讨论;
- 判断是否为回归(确认 bug 在上一版本中是否存在);
- 检查是否已有相同 issue 打开;
- 如需要,新开 issue;
- 如果是回归,决定其对本次发布的严重程度(criticality)。
发布测试与签核(Sign-off)
- 团队按发布检查清单执行,其中包括WinGet 配置的测试;
- 签核流程:
- 各 Teams 对自己负责的模块独立签核;
- 首个 RC 中发现的回归会产生 PR 修复;
- 第二个 RC 验证修复是否生效;
- Command Palette 需要单独签核;
- 最终验证确保各模块与 Command Palette 集成时不会崩溃。
六、PR 管理与发布流程
PR 评审机制
- PM 团队通常会给 PR 打上"need review"标签以引起注意;
- 不改变太多内容的社区小修复通常会被直接接受;
- PM 会设置优先级(有时使用 "info.90" 之类的标签),并决定哪些 PR 优先处理;
- 在时间允许的情况下,团队成员可以帮助推动 PR 合入。
审批要求
- PR 合并前必须获得 code owners 的批准;
- 新团队成员可以审批 PR,但最终批准权在 code owners 手中。
优先级处理
- 优先级不高的老 PR 有时会"被遗漏"(slip through the cracks);
- PM 会用"priority one"标签标注必须进入本次发布的 PR;
- Draft(草稿)PR 通常不会被优先处理。
特定类型的 PR
- CI 相关 PR 需要评审并经过 code owner 批准;
- 功能新增(如 GPO 支持)需要 PM 先决定该功能是否被需要;
- 与 Watson 错误相关的 bug 修复有时没有对应的 issue 链接;
- Command Palette 被视为即将发布的版本中的高优先级项目。
七、项目管理注意事项
指南最后给出了主干(main 分支)管理方面的纪律性要求:
- 不要把未完成的功能合入 main;
- 进行中的工作应使用feature 分支,命名约定为
feature/name-of-feature; - 涉及安装器文件(installer files)的 PR 必须仔细评审——仓库中 installer/ 目录下的 .wxs 组件、Bootstrapper wixproj 等都属于这一敏感范围;
- 未完成的功能要么等完成后再合并,要么置于实验性开关(experimentation flags)之后才允许进入 main。
小结
PowerToys 的开发规范围绕三条主线展开:供应链安全(MIT 优先 + NOTICE.md 登记 + 全量代码签名 + CI 签名检查)、发布质量(干净构建 + 模块 sanity check + 双 RC 回归验证 + 分模块签核)、基础设施要求(多机/多屏测试、OneFuzz 模糊测试、CsWinRT 与 .NET SDK 的运行时版本对齐)。结合仓库中 src/runner/powertoy_module.cpp 的模块动态加载实现、Directory.Packages.props 的版本约束注释以及 doc/devdocs/tools/fuzzingtesting.md 的 fuzzing 配置,这些规范在代码层面均有可验证的对应物。对于希望参与 PowerToys 开发或理解其工程质量体系的读者,这份指南及其关联文档是最直接的切入点。
【免费下载链接】PowerToysMicrosoft PowerToys is a collection of utilities that supercharge productivity and customization on Windows项目地址: https://gitcode.com/GitHub_Trending/po/PowerToys
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考