发布时间:2026/9/5 16:56:04
PowerToys 新模块开发端到端指南:从模块模板到设置集成、调试与打包 PowerToys 新模块开发端到端指南从模块模板到设置集成、调试与打包【免费下载链接】PowerToysMicrosoft PowerToys is a collection of utilities that supercharge productivity and customization on Windows项目地址: https://gitcode.com/GitHub_Trending/po/PowerToys本文基于 PowerToys 官方开发者文档 Creating a new PowerToy: end-to-end developer guide 整理扩写完整覆盖从零构建一个 PowerToys 工具模块的全流程模块类型选型、模块接口Module Interface的关键方法、服务工程搭建、设置系统集成、调试技巧、WiX 安装包集成以及测试与 OOBE 收尾。读完后你可以独立完成一个新模块从模板初始化、runner 注册、设置页面接线到可打包交付的全部工作并理解 runner 与模块 DLL 之间的加载机制。1. 概览与前置条件PowerToy 模块是一个自包含self-contained的工具单元集成在 PowerToys 生态内可以是纯 UI 型、纯后台服务型或者两者兼有。1.1 环境要求先按照 Getting Started 指南配置好开发环境然后参照 调试文档 验证自己能够构建并运行PowerToys.slnx。可选WiX v5 工具集用于制作安装包。1.2 标准目录结构原文档约定的模块目录布局如下所有模块逻辑都应隔离在src/modules/YourModule之下src/ modules/ your_module/ YourModule.sln YourModuleInterface/ YourModuleUI/ (if needed) YourModuleService/ (if needed)从源码结构看ModuleInterface工程产出的是ModuleInterface.dll供 runner 在运行时加载并调用UI 与 Service 工程则按需拆分。2. 设计与规划先确定模块类型再写接口2.1 选择模块类型写代码前先想清楚三件事需要什么样的 UI、生命周期如何、它是常驻服务还是事件驱动。文档给出了四类典型场景并推荐对照相似的现有模块来研究UI-only纯界面例如 ColorPicker可参考 src/modules/colorPickerBackground service后台服务例如 LightSwitch、Awake可参考 src/modules/LightSwitch 与 src/modules/awakeHybridUI 后台逻辑混合例如 ShortcutGuide可参考 src/modules/ShortcutGuideC/C# 互操作例如 PowerRename可参考 src/modules/powerrename。模块主体既可以用 C 编写也可以用 C# 编写。2.2 模块接口的关键成员模块入口是ModuleInterface模板中为dllmain.cpp核心类继承自PowertoyModuleIface。当前仓库中的接口定义位于 powertoy_module_interface.h其中声明了get_name、get_key、get_config、set_config、enable、disable、is_enabled、destroy等纯虚函数以及带默认实现的get_hotkeys、on_hotkey、is_enabled_by_default、gpo_policy_enabled_configuration等方法见该文件约 89–156 行。文档要求你在模板中理解并改造以下九组关键成员1设置结构体ModuleSettings这是模块设置项的存放处值类型可以是字符串、bool、int甚至自定义枚举struct ModuleSettings {};2接口类声明完整类定义继承PowertoyModuleIface私有成员通常包含启用状态、事件处理逻辑或热键相关字段公有部分包含构造函数与初始化逻辑class ModuleInterface : public PowertoyModuleIface { private: // the private members of the class // Can include the enabled variable, logic for event handlers, or hotkeys. public: // the public members of the class // Will include the constructor and initialization logic. }注意类中许多函数是样板代码只需把模块名做简单的字符串替换下面列出的其余函数才需要较大改动。3GPO 组策略支持GPOGroup Policy Object允许管理员在一组机器上统一下发策略。你的模块必须出现在 GPO 的设置列表中并实现gpo_policy_enabled_configuration返回对应模块的策略值。实现上可以右键powertoys_gpo对象跳转到定义为模块配置getConfiguredModuleEnabledValuevirtual powertoys_gpo::gpo_rule_configured_t gpo_policy_enabled_configuration() override { return powertoys_gpo::getConfiguredModuleEnabledValue(); }4init_settings()初始化设置从已存在的settings.json读取配置文件不存在时保留默认值void ModuleInterface::init_settings()5get_config向设置面板描述配置Runner 调用它获取settings.json中该模块的配置描述序列化为 JSON 写入缓冲virtual bool get_config(wchar_t* buffer, int* buffer_size) override6set_config接收新设置设置面板提交的新值会以序列化 JSON 传入模块负责解析并持久化virtual void set_config(const wchar_t* config) override7call_custom_action自定义动作当模块使用custom_action类型的设置项时设置面板点击按钮会触发该方法void call_custom_action(const wchar_t* action) override8生命周期函数控制模块的启用/禁用状态以及默认是否启用virtual void enable() // starts the module virtual void disable() // terminates the module and performs any cleanup virtual bool is_enabled() // returns if the module is currently enabled virtual bool is_enabled_by_default() const override // allows the module to dictate whether it should be enabled by default in the PowerToys app.9热键函数负责热键的解析、上报与响应// takes the hotkey from settings into a format that the interface can understand void parse_hotkey(PowerToysSettings::PowerToyValues settings) // returns the hotkeys from settings virtual size_t get_hotkeys(Hotkey* hotkeys, size_t buffer_size) override // performs logic when the hotkey event is fired virtual bool on_hotkey(size_t hotkeyId) override2.3 设计原则模块逻辑隔离在/modules/YourModule下禁止跨模块直接依赖优先复用 src/common 中的共享工具库如 DPI 辅助dpi_aware.h、显示器枚举monitors.h等init/set/get config 都通过预设函数访问设置核心实现在src/common/SettingsAPI的 settings_helpers.h 与 settings_objects.h 中PowerToysSettings::Settings支持add_bool_toggle、add_int_spinner、add_string、add_color_picker、add_custom_action等控件类型PowerToyValues提供load_from_settings_file/save_to_settings_file持久化方法。3. 模块脚手架Bootstrapping使用 PowerToy 模块模板 生成模块接口的起始代码。模板安装方式见 tools/project_template/README.md把ModuleTemplate.zip放入%USERPROFILE%\Documents\Visual Studio 2022\Templates\ProjectTemplates\VS 2026 对应Visual Studio 18目录之后在 Visual Studio 新建工程时于 Visual C 选项卡下即可看到。把全部工程与命名空间替换为你的模块名。模板文件 dllmain.cpp 中使用$projectname$/$safeprojectname$占位符例如const static wchar_t* MODULE_NAME L$projectname$;。更新.vcxproj与解决方案文件中的 GUID。用你自己的逻辑实现第 2 节提到的各函数。注册模块——这是模块能被 runner 检测到的必要步骤。原文档列出的注册清单包括src/runner/modules.hsrc/runner/modules.cppsrc/runner/resource.hsrc/runner/settings_window.hsrc/runner/settings_window.cppsrc/runner/main.cppsrc/common/logger.h日志小技巧在 runner 代码中搜索已有模块名如LightSwitch可以快速定位这些清单。从当前仓库源码可以确认runner 在 src/runner/main.cpp 中维护了knownModules列表逐项形如LPowerToys.LightSwitchModuleInterface.dll随后在循环中调用load_powertoy(moduleSubdir)加载并以pt_module-get_key()为键存入modules()设置页映射在 src/runner/settings_window.h 的ESettingsWindowNames枚举与 src/runner/settings_window.cpp 中成对出现模板 README 还补充说明模块 DLL 名需加入 src/runner/main.cpp 的known_dlls映射才能在运行时被加载。ModuleInterface工程必须产出ModuleInterface.dll这样 runner 才能与服务交互。经验提示模块 ID 不一致manifest、注册表、服务之间是最常见的加载失败原因之一务必保持一致。4. 编写服务Service每个 PowerToy 的服务形态都不同。建议先在独立工程中开发应用主体再接入 PowerToys 的设置逻辑但服务必须先于 runner 接线完成。要点服务是与 Module Interface 相互独立的项目可用 C# 或 C 编写服务图标通过.rc文件设置服务名在.vcxproj中通过TargetName设置例如PropertyGroup OutDir..\..\..\..\$(Platform)\$(Configuration)\$(MSBuildProjectName)\/OutDir TargetNamePowerToys.LightSwitchService/TargetName /PropertyGroup需要查看.vcxproj内容时右键工程选择Unload project服务内读取设置的推荐写法ModuleSettings单例随服务代码提供可参考 src/modules/LightSwitch 中的实现并按需裁剪ModuleSettings::instance().InitFileWatcher(); ModuleSettings::instance().LoadSettings(); auto settings ModuleSettings::instance().settings();如果模块带用户界面使用WinUI Blank App模板建工程遵循 Windows 设计最佳实践借助 WinUI 3 Gallery 应用辅助 UI 编码。5. 设置系统集成PowerToys 的设置按模块以 JSON 形式存放在%LOCALAPPDATA%\Microsoft\PowerToys\module\settings.json5.1 C# 侧实现步骤在src\settings-ui\Settings.UI.Library\下创建moduleProperties.cs与moduleSettings.cs。Properties中定义所有设置的默认值需与 Module Interface 中声明的设置项一一对应moduleSettings.cs负责构建settings.json对象结构应匹配public ModuleSettings() { Name ModuleName; Version Assembly.GetExecutingAssembly().GetName().Version.ToString(); Properties new ModuleProperties(); // settings properties you set above. }在src\settings-ui\Settings.UI\ViewModels下创建moduleViewModel.cs——它是 PowerToys 应用内设置页与磁盘设置文件之间的交互层。此处的变更会通过NotifyPropertyChanged事件触发设置监听器在src\settings-ui\Settings.UI\SettingsXAML\Views创建SettingsPage.xaml即用户与模块设置交互的页面面向用户的字符串必须走资源串以便本地化x:Uid关联 Resources.resw// LightSwitch.xaml ComboBoxItem x:UidLightSwitch_ModeOff AutomationProperties.AutomationIdOffCBItem_LightSwitch TagOff / // Resources.resw data nameLightSwitch_ModeOff.Content xml:spacepreserve valueOff/value /data重要上面示例用.Content定位 ComboBox 的内容这个后缀会随控件类型变化例如.Text、.Header等。提醒通过外部编辑器VS Code、记事本的手工修改不会触发设置监听器只有通过 PowerToys 写入的变更才会触发重载。这一行为与 C 侧的文件监听机制src/common/SettingsAPI中的 FileWatcher.h相对应。5.2 常见坑只使用 WinUI 3 框架不要使用 UWP从非 UI 线程更新 UI 时必须使用DispatcherQueue。6. 构建与调试6.1 调试步骤首次调试 PowerToys 的开发者请先完成 调试文档 中的预调试准备将runner设为启动项目并确认构建配置与系统架构ARM64/x64一致按F5或点击Local Windows Debugger按钮开始调试runner 会随之启动若要为服务设断点按 CtrlAltP 搜索你的服务进程并附加到 runner用日志记录改动。日志位置Runner 日志%LOCALAPPDATA%\Microsoft\PowerToys\RunnerLogs模块日志%LOCALAPPDATA%\Microsoft\PowerToys\Module\Service\version提示PowerToys 会激进缓存.nuget产物构建行为异常时可用git clean -xfd清理。runner 侧的加载行为可以在 src/runner/main.cpp 中看到佐证Debug 模式下某个模块加载失败只会Logger::warn记录并继续执行便于开发者快速迭代不必为调试单个模块而构建全部模块。7. 安装包与打包WiX7.1 把模块加入安装器通过 NuGet 为 WiX5 安装WixToolset.Heat在installer\PowerToysInstallerVNext目录为你的模块新增一个Module.wxs文件例如 installer/LightSwitch.wxs 可作为参照格式拷贝其他模块如 Light Switch的 wxs 格式替换字符串与 GUID 值关键占位符是!--ModuleNameFiles_Component_Def--——它会被generateFileComponents.ps1生成的组件代码替换当前仓库中对应的生成脚本为 installer/generateAllFileComponents.ps1在 installer/Product.wxs 的Feature IdCoreFeature ... 段落中加入一行ComponentGroupRef IdModuleComponentGroup /在文件组件生成脚本末尾按如下格式为新模块追加条目-fileListName ModuleFiles需与Module.wxs中设置的字符串一致ModuleServiceName需与服务 exe 名一致# Module Name Generate-FileList -fileDepsJson -fileListName ModuleFiles -wxsFilePath $PSScriptRoot\Module.wxs -depsPath $PSScriptRoot..\..\..\$platform\Release\ModuleServiceName Generate-FileComponents -fileListName ModuleFiles -wxsFilePath $PSScriptRoot\Module.wxs -regroot $registryroot8. 测试与验证8.1 UI 测试测试工程放在/modules/YourModule/Tests新建 WinUI Unit Test App参照现有模块如 Light Switch的测试写法可测试独立的 UI如 Color Picker 类模块也可以验证 PowerToys 应用内的设置 UI 是否真正控制到了你的服务。8.2 手动验证清单在 PowerToys Settings 中启用/禁用模块检查日志中的初始化记录确认图标、工具提示tooltips与 OOBE 页面正确显示。8.3 实用技巧验证睡眠/唤醒与提权elevation状态。后台模块若在事件句柄未在恢复后重建唤醒后往往静默失效用 Windows Sandbox 模拟干净安装环境想模拟“新用户”可删除%LOCALAPPDATA%\Microsoft下的 PowerToys 文件夹。8.4 快捷键冲突检测如果模块带快捷键必须按设置实现文档中 Shortcut conflict detection 章节的步骤正确注册以获得冲突检测能力。runner 侧的冲突检测实现可参考 src/runner/hotkey_conflict_detector.cpp 与集中式热键管理 src/runner/centralized_hotkeys.cpp。9. 收尾工作9.1 OOBEOut-of-Box Experience页面OOBE 页面是一个自定义设置页在新用户首次使用以及更新之后、正式设置应用打开之前显示让用户一眼了解各模块用途。需要在src\settings-ui\Settings.UI\SettingsXAML\OOBE\Views创建OOBEModuleName.xaml把模块名加入src\settings-ui\Settings.UI\OOBE\Enums\PowerToysModules.cs中的枚举。9.2 模块资源Assets模块功能完成后需要规划对外展示的资源Module Icon显示在 OOBE 页面、README、PowerToys 主页、模块设置页等多处Module Image各模块设置页顶部的图片OOBE ImageOOBE 页面上每个模块的头部图。说明图标与截图的具体设计由设计团队在应用内部保证一致性。如果你有关图标或截图的构想可以写在 PR 的 Additional Comments 部分供团队参考。9.3 文档提交新 PowerToy 需要两类文档开发者文档放在仓库/doc/devdocs/modules/如 doc/devdocs/modules/readme.md 目录面向开发者说明如何接手维护你的模块应涵盖架构、关键文件、测试与调试技巧Microsoft Learn 文档当模块准备合入 PowerToys 仓库时由内部团队成员编写面向用户的 Learn 文档。开发者在此步骤工作量不大但需留意 PR 动态及时补充团队索要的信息。10. 小结新模块接入检查单阶段关键动作验证方式设计确定 UI-only / 服务 / 混合 / 互操作类型找到最相似的现有模块作参照脚手架模板生成、替换占位符与 GUIDModuleTemplate.dll工程可编译注册加入 runner 的模块 DLL 清单与设置窗口映射在 src/runner/main.cpp 的knownModules与 settings_window.h 中搜到模块名服务独立工程先行TargetName命名ModuleSettings读设置服务可独立运行并读写%LOCALAPPDATA%\Microsoft\PowerToys\module\settings.json设置集成Properties/Settings/ViewModel/XAML/resw 五件套设置面板改动触发文件监听并写回 JSON调试runner 为启动项目CtrlAltP 附加服务RunnerLogs与模块Module\Service日志正常打包Module.wxsProduct.wxs引用 生成脚本条目安装包生成成功干净环境Windows Sandbox验证测试WinUI 单元测试 手动验证 OOBE 检查启用/禁用、唤醒恢复、新用户场景均通过如果你在使用过程中需要帮助按文档建议提一个带Needs-Team-Response标签的 issue 以获得团队关注。【免费下载链接】PowerToysMicrosoft PowerToys is a collection of utilities that supercharge productivity and customization on Windows项目地址: https://gitcode.com/GitHub_Trending/po/PowerToys创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

2026/9/5 16:56:04

树莓派Shell工程化实战:从系统配置、GPIO到YOLOv5部署

最近围绕树莓派的一场 Tech Talk 里,高频出现了三个看起来不在同一个层面的词:树莓派生态、JishuShell、上海晶珩。树莓派生态容易理解,就是把板卡、系统、外设、社区和项目串起来看;上海晶珩这类本地硬件与服务伙伴的角色也相对清…

2026/9/5 17:56:06

C++控制台学生成绩管理系统:内存、编码与状态机实战

简介:本资源是一套完整的C课程设计项目——控制台版学生成绩管理系统,面向计算机专业本科生及C初学者,解决课程实践环节中数据结构应用、模块化编程与小型系统开发能力训练问题。系统实现五大核心功能:成绩录入与修改、单学生查询…

2026/9/5 17:56:06

淡水观赏鱼视觉数据集:分类+检测+分割三位一体训练集

简介:本资源是面向计算机视觉研究者与AI工程师的淡水鱼类多任务数据集,聚焦图像分类、目标检测与语义分割三大核心任务,适用于生物识别、水族馆智能管理、淡水生态监测等实际场景。数据包共980个文件,含977张高质量JPG淡水鱼实拍图…

2026/9/5 17:51:06

yfinance 3 分钟实战指南:拉取雅虎财经行情数据

yfinance 3 分钟实战指南:拉取雅虎财经行情数据 【免费下载链接】yfinance Download market data from Yahoo! Finances API 项目地址: https://gitcode.com/GitHub_Trending/yf/yfinance 假设你要搭一个回测环境,手上一份策略需要十几只标的十年…

2026/9/5 2:46:54

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/9/5 2:46:52

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/9/5 2:44:34

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/9/5 0:04:47

流式背压机制:避免前端渲染卡死与内存暴涨的滑动窗口限流

流式背压机制:避免前端渲染卡死与内存暴涨的滑动窗口限流在大模型流式输出(Streaming)与智能体实时推流的架构中,生产环境中经常出现一种“上下游生产消费速率严重失衡”的极端情况: 生产端极速产出:大模型…

2026/9/5 2:45:13

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/5 2:30:42

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/5 2:46:50

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…