This page covers how the PowerToys Runner discovers and loads module DLLs at startup, the PowertoyModuleIface contract that every module DLL must implement, the PowertoyModule wrapper the runner uses to track loaded instances, and how module lifecycle transitions (enable, disable, destroy) are managed at runtime.
For the Runner's overall startup sequence, tray icon, and message loop, see 2.1 For how module settings are read from disk and applied after loading, see 2.3 For the IPC protocol between the Runner and Settings UI, see 2.4 For a developer guide to implementing a new module, see 7.3
Every PowerToys module is packaged as a Windows DLL. The Runner:
LoadLibrary on each path and resolves an exported factory function.PowertoyModuleIface*.PowertoyModule RAII object and stores it in the global modules() map.start_enabled_powertoys() to activate any module that should be running on launch.No filesystem scanning takes place; the list of DLLs is determined at compile time.
knownModules ListThe static list of module DLLs is defined in src/runner/main.cpp. Each entry is a path relative to the runner executable's directory. There are two path prefixes in use:
| Prefix | Location | Module type |
|---|---|---|
| (none) | Same directory as PowerToys.exe | Native / MFC / mixed-mode modules |
WinUI3Apps/ | WinUI3Apps\ subdirectory | WinUI3-based modules |
knownModules vector โ src/runner/main.cpp256-290
| DLL path | Module |
|---|---|
PowerToys.FancyZonesModuleInterface.dll | FancyZones |
PowerToys.powerpreview.dll | File Explorer add-ons (preview handlers) |
WinUI3Apps/PowerToys.ImageResizerExt.dll | Image Resizer |
PowerToys.KeyboardManager.dll | Keyboard Manager |
PowerToys.Launcher.dll | PowerToys Run |
WinUI3Apps/PowerToys.PowerRenameExt.dll | PowerRename |
PowerToys.ShortcutGuideModuleInterface.dll | Shortcut Guide |
PowerToys.ColorPicker.dll | Color Picker |
PowerToys.AwakeModuleInterface.dll | Awake |
PowerToys.FindMyMouse.dll | Find My Mouse |
PowerToys.MouseHighlighter.dll | Mouse Highlighter |
PowerToys.MouseJump.dll | Mouse Jump |
PowerToys.AlwaysOnTopModuleInterface.dll | Always on Top |
PowerToys.MousePointerCrosshairs.dll | Mouse Pointer Crosshairs |
PowerToys.CursorWrap.dll | Cursor Wrap |
PowerToys.PowerAccentModuleInterface.dll | Quick Accent |
PowerToys.PowerOCRModuleInterface.dll | Text Extractor |
PowerToys.AdvancedPasteModuleInterface.dll | Advanced Paste |
WinUI3Apps/PowerToys.FileLocksmithExt.dll | File Locksmith |
WinUI3Apps/PowerToys.RegistryPreviewExt.dll | Registry Preview |
WinUI3Apps/PowerToys.MeasureToolModuleInterface.dll | Screen Ruler |
WinUI3Apps/PowerToys.NewPlus.ShellExtension.dll | New+ |
WinUI3Apps/PowerToys.HostsModuleInterface.dll | Hosts File Editor |
WinUI3Apps/PowerToys.Peek.dll | Peek |
WinUI3Apps/PowerToys.EnvironmentVariablesModuleInterface.dll | Environment Variables |
PowerToys.MouseWithoutBordersModuleInterface.dll | Mouse Without Borders |
PowerToys.CropAndLockModuleInterface.dll | Crop And Lock |
PowerToys.CmdNotFoundModuleInterface.dll | Command Not Found |
PowerToys.WorkspacesModuleInterface.dll | Workspaces |
PowerToys.CmdPalModuleInterface.dll | Command Palette |
PowerToys.ZoomItModuleInterface.dll | ZoomIt |
PowerToys.LightSwitchModuleInterface.dll | Light Switch |
Sources: src/runner/main.cpp256-290
Diagram: Module Loading Sequence (runner startup)
Sources: src/runner/main.cpp244-319
If a DLL fails to load, the behavior differs by build configuration:
MessageBoxW with the path that failed, then continues. The error message prefix is POWER_TOYS_MODULE_LOAD_FAIL defined as "Failed to load ". src/runner/main.cpp309-315In both cases, the runner does not abort startup if a module DLL is missing or crashes during construction.
PowertoyModuleIface and PowertoyModuleDiagram: Relationship between runner types and the module interface
Sources: src/runner/powertoy_module.h src/runner/powertoy_module.cpp src/runner/general_settings.cpp222-262 src/runner/settings_window.cpp41-56
PowertoyModuleIface MethodsThe interface is declared in src/modules/interface/powertoy_module_iface.h. Each module DLL implements it and exports a factory function (commonly named powertoy_create) that the runner resolves with GetProcAddress inside load_powertoy.
| Method | Called by | Purpose |
|---|---|---|
get_key() | load_powertoy | Returns display name used as map key (e.g., "FancyZones") |
is_enabled() | get_general_settings, apply_module_status_update | Queries current activation state |
enable() | start_enabled_powertoys, apply_module_status_update | Activates module (installs hooks, spawns child process, etc.) |
disable() | apply_module_status_update | Deactivates module |
get_config() | โ | Returns module settings as a JSON string |
set_config(settings) | send_json_config_to_module | Applies updated settings from Settings UI |
call_custom_action(action) | dispatch_json_action_to_module | Handles button actions triggered in Settings UI |
gpo_policy_enabled_configuration() | apply_module_status_update | Returns GPO enforcement override for the module |
destroy() | PowertoyModule destructor | Releases all module resources |
PowertoyModule WrapperPowertoyModule (defined in src/runner/powertoy_module.h / src/runner/powertoy_module.cpp) is the runner-side owner of a loaded module instance. It:
HMODULE returned by LoadLibrary and the PowertoyModuleIface* obtained from the factory.operator->() to forward calls to the interface.json_config(), remove_hotkey_records(), update_hotkeys(), and UpdateHotkeyEx() as runner-managed hotkey bookkeeping operations that the raw interface does not provide.destroy() on the interface and FreeLibrary on the handle when it is destroyed.The modules() function returns a reference to a process-wide std::map<std::wstring, PowertoyModule>. Initialization order of this singleton is managed explicitly in WinMain before runner() is called. src/runner/main.cpp550-551
Diagram: Module state transitions
Sources: src/runner/general_settings.cpp196-290 src/runner/main.cpp318-319
The function apply_module_status_update in src/runner/general_settings.cpp handles enable/disable changes originating from the Settings UI (via IPC) or from GPO policy checks. The full sequence is:
PowertoyModule in modules().gpo_policy_enabled_configuration(). If GPO enforces a state, override the requested value.powertoy->enable() or powertoy->disable().HotkeyConflictManager (EnableHotkeyByModule / DisableHotkeyByModule).powertoy.UpdateHotkeyEx() to sync hotkey registrations with the new state.general_settings JSON file.src/runner/general_settings.cpp196-290
start_enabled_powertoysCalled once after all DLLs are loaded. Declared in src/runner/general_settings.h src/runner/general_settings.h42 Iterates modules() and calls enable() on each module whose key appears as enabled in the loaded general settings JSON (or whose GPO policy forces it on). Modules not present in the enabled map are left in the disabled state.
Modules use two runtime patterns. The PowertoyModuleIface contract is identical in both cases; only the implementation of enable() and disable() differs.
Diagram: In-process vs. child-process module patterns
In-process modules install Windows hooks or register COM objects directly inside the runner process. Examples: FancyZones, Mouse Highlighter, Always on Top.
Child-process modules spawn a separate executable when enable() is called and terminate it when disable() is called. The DLL interface manages the child process handle. Examples: PowerToys Run (PowerToys.PowerLauncher.exe), Keyboard Manager engine, Awake, and all WinUI3-based modules in WinUI3Apps/.
The WinUI3 modules (those loaded from WinUI3Apps/) always follow the child-process pattern: the DLL's enable() launches the corresponding WinUI3 packaged app, and disable() terminates it.
When the Settings UI sends updated configuration over the IPC pipe, dispatch_received_json in src/runner/settings_window.cpp routes it:
"powertoys" key โ dispatch_json_config_to_modules โ send_json_config_to_module โ calls set_config(settings) on the target PowertoyModuleIface. src/runner/settings_window.cpp167-192"action" key โ dispatch_json_action_to_module โ calls call_custom_action(element) on the target. src/runner/settings_window.cpp67-148"module_status" key โ apply_module_status_update, which calls enable() or disable(). src/runner/settings_window.cpp221-226"refresh" key โ collects all module configs via get_power_toys_settings() (which calls json_config() on every PowertoyModule) and sends the full settings object back to the UI. src/runner/settings_window.cpp41-56Sources: src/runner/settings_window.cpp41-357
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.