Overview
Every PowerToys module must implement thePowertoyModuleIface interface, which defines a standardized contract between the module and the Runner. This interface enables the Runner to load, configure, enable, disable, and communicate with modules in a consistent manner.
PowertoyModuleIface Definition
The module interface is defined insrc/modules/interface/powertoy_module_interface.h:
src/modules/interface/powertoy_module_interface.h:37-171
Module Lifecycle
The Runner interacts with modules following this lifecycle:src/modules/interface/powertoy_module_interface.h:6-35
Implementing a Simple Module
Here’s a complete example of a simple module implementation based on Find My Mouse:1. Basic Module Class
src/modules/MouseUtils/FindMyMouse/dllmain.cpp:62-110
2. Settings Support
Add configuration management to your module:src/modules/MouseUtils/FindMyMouse/dllmain.cpp:206-246
3. Hotkey Support
Add hotkey handling to your module:src/modules/MouseUtils/FindMyMouse/dllmain.cpp:183-203
4. Multiple Hotkeys
For modules with multiple hotkeys (like Advanced Paste):get_hotkeys() must match the order expected by the Settings UI for conflict detection.
Reference: src/modules/AdvancedPaste/AdvancedPasteModuleInterface/dllmain.cpp:1053-1071
External Application Module
For modules that launch separate applications (like Color Picker):src/modules/colorPicker/ColorPicker/dllmain.cpp:48-309
Group Policy Support
Add GPO support to allow enterprise policy control:- Add your module’s GPO function to
src/common/utils/gpo.h:
- Define the policy registry key in
src/common/utils/gpo.h:
src/modules/MouseUtils/FindMyMouse/dllmain.cpp:112-115
Telemetry
Implement telemetry to track usage:src/modules/colorPicker/ColorPicker/dllmain.cpp:161, doc/devdocs/core/settings/telemetry.md
DLL Entry Point
Every module DLL needs aDllMain function:
src/modules/MouseUtils/FindMyMouse/dllmain.cpp:38-54
Best Practices
Memory Management
- Clean up in
disable(): Free resources, stop threads, close handles - Final cleanup in
destroy(): Calldisable()anddelete this - Check enabled state: Guard operations with
if (m_enabled)
Threading
- Don’t block
enable(): Spawn threads for long-running operations - Clean thread shutdown: Use events or flags to signal threads to exit
- Detach or join: Either detach threads or properly join them in
disable()
Hotkeys
- Fast handlers: Hotkey handlers must execute quickly to avoid Windows deregistering the hook
- Spawn threads: Move actual work to background threads
- Return quickly: Return from
on_hotkey()within milliseconds
src/modules/AdvancedPaste/AdvancedPasteModuleInterface/dllmain.cpp:990-998
Settings
- Validate input: Check ranges and types when parsing settings
- Provide defaults: Always have sensible fallback values
- Persist changes: Call
save_to_settings_file()after user changes - Apply immediately: Update running state when settings change
Logging
- Initialize logger: Call
LoggerHelpers::init_logger()in constructor - Use appropriate levels:
trace,info,warn,error - Include context: Log module name and operation details
- Don’t spam: Avoid logging in hot paths
src/modules/MouseUtils/FindMyMouse/dllmain.cpp:87-88
Testing Your Module
Manual Testing
- Build your module: Place DLL in
modules/folder - Restart Runner: Kill
PowerToys.exeand restart - Check Settings UI: Your module should appear in Settings
- Test enable/disable: Toggle module and verify behavior
- Test hotkeys: Press configured hotkeys and check logs
- Test settings: Change settings and verify they apply
Debugging
- Attach debugger to
PowerToys.exeprocess - Set breakpoints in your module’s DLL code
- Check logs:
%LOCALAPPDATA%\Microsoft\PowerToys\logs\ - Use debug builds: Debug symbols help tremendously
Complete Example: Simple Module
Here’s a complete minimal module that appears in Settings and logs when enabled:Next Steps
Settings System
Learn how to create a Settings UI for your module
Runner Implementation
Understand how the Runner loads and manages modules
Architecture Overview
High-level system architecture
Common Libraries
Shared utilities you can use in your module