This PR contains a set of bug fixes and general improvements to [Awake](https://awake.den.dev/) and developer experience tooling for building the module. ### Awake Fixes - **#32544** - Fixed an issue where Awake settings became non-functional after the PC wakes from sleep. Added `WM_POWERBROADCAST` handling to detect system resume events (`PBT_APMRESUMEAUTOMATIC`, `PBT_APMRESUMESUSPEND`) and re-apply `SetThreadExecutionState` to restore the awake state. - **#36150** - Fixed an issue where Awake would not prevent sleep when AC power is connected. Added `PBT_APMPOWERSTATUSCHANGE` handling to re-apply `SetThreadExecutionState` when the power source changes (AC/battery transitions). - **#41674** - Fixed silent failure when `SetThreadExecutionState` fails. The monitor thread now handles the return value, logs an error, and reverts to passive mode with updated tray icon. - **#41738** - Fixed `--display-on` CLI flag default from `true` to `false` to align with documentation and PowerToys settings behavior. This is a breaking change for scripts relying on the undocumented default. - **#41918** - Fixed `WM_COMMAND` message processing flaw in `TrayHelper.WndProc` that incorrectly compared enum values against enum count. Added proper bounds checking for custom tray time entries. - **#44134** - Documented that `ES_DISPLAY_REQUIRED` (used when "Keep display on" is enabled) blocks Task Scheduler idle detection, preventing scheduled maintenance tasks like SSD TRIM. Workaround: disable "Keep display on" or manually run `Optimize-Volume -DriveLetter C -ReTrim`. - **#38770** - Fixed tray icon failing to appear after Windows updates. Increased retry attempts and delays for icon Add operations (10 attempts, up to ~15.5 seconds total) while keeping existing fast retry behavior for Update/Delete operations. - **#40501** - Fixed tray icon not disappearing when Awake is disabled. The `SetShellIcon` function was incorrectly requiring an icon for Delete operations, causing the `NIM_DELETE` message to never be sent. - Fixed an issue where toggling "Keep screen on" during an active timed session would disrupt the countdown timer. The display setting now updates directly without restarting the timer, preserving the exact remaining time. ### Performance Optimizations - Fixed O(n²) loop in `TrayHelper.CreateAwakeTimeSubMenu` by replacing `ElementAt(i)` with `foreach` iteration. - Fixed Observable subscription leak in `Manager.cs` by storing `IDisposable` and disposing in `CancelExistingThread()`. Also removed dead `_tokenSource` code that was no longer used. - Reduced allocations in `SingleThreadSynchronizationContext` by changing `Tuple<>` to `ValueTuple`. - Replaced dedicated exit event thread with `ThreadPool.RegisterWaitForSingleObject()` to reduce resource usage. ### Code Quality - Replaced `Console.WriteLine` with `Logger.LogError` in `TrayHelper.cs` for consistent logging. - Added proper error logging to silent exception catches in `AwakeService.cs`. - Removed dead `Math.Min(minutes, int.MaxValue)` code where `minutes` is already an `int`. - Extracted hardcoded tray icon ID to named constant `TrayIconId`. - Standardized null coalescing for `GetSettings<AwakeSettings>()` calls across all files. ### Debugging Experience Fixes - Fixed first-chance exceptions in `settings_window.cpp` during debugging. Added `HasKey()` check before accessing `hotkey_changed` property to prevent `hresult_error` exceptions when the property doesn't exist in module settings. - Fixed first-chance exceptions in FindMyMouse `parse_settings` during debugging. Refactored to extract the properties object once and added `HasKey()` checks before all `GetNamedObject()` calls. This prevents `winrt::hresult_error` exceptions when optional settings keys (like legacy `overlay_opacity`) don't exist, improving the debugging experience by eliminating spurious exception breaks. - Fixed LightSwitch.UITests build failures when building from a clean state. Added missing project references (`ManagedCommon`, `LightSwitchModuleInterface`) with `ReferenceOutputAssembly=false` to ensure proper build ordering, and added existence check for the native DLL copy operation. ### Developer Experience - Added `setup-dev-environment.ps1` script to automate development environment setup. - Added `clean-artifacts.ps1` script to resolve build errors from corrupted build state or missing image files. - Added build script that allows standalone command line build of the Awake module. - Added troubleshooting section to `doc/devdocs/development/debugging.md` with guidance on resolving common build errors.
PowerToys Developer Documentation
Welcome to the PowerToys developer documentation. This documentation provides information for developers who want to contribute to PowerToys or understand how it works.
Core Architecture
- Architecture Overview - Overview of the PowerToys architecture and module interface
- Runner and System tray - Details about the PowerToys Runner process
- Settings - Documentation on the settings system
- Installer - Information about the PowerToys installer
- Modules - Documentation for individual PowerToys modules
Common Components
- Context Menu Handlers - How PowerToys implements and registers Explorer context menu handlers
- Monaco Editor - How PowerToys uses the Monaco code editor component across modules
- Logging and Telemetry - How to use logging and telemetry
- Localization - How to support multiple languages
Development Guidelines
- Coding Guidelines - Development guidelines and best practices
- Coding Style - Code formatting and style conventions
- UI Testing - How to write UI tests for PowerToys
- Debugging - Techniques for debugging PowerToys
Tools
- Tools Overview - Overview of tools in PowerToys
- Build Tools - Tools that help building PowerToys
- Bug Report Tool - Tool for collecting logs and system information
- Debugging Tools - Specialized tools for debugging
- Fuzzing Testing - How to implement and run fuzz testing for PowerToys modules
Processes
- Release Process - How PowerToys releases are prepared and published
- Update Process - How PowerToys updates work
- GPO Implementation - Group Policy Objects implementation details
Other Resources
- aka.ms links - List of short links
- Issue/PR commands - Special commands for managing issues and pull requests
Fork, Clone, Branch and Create your PR
Once you've discussed your proposed feature/fix/etc. with a team member, and an approach or a spec has been written and approved, it's time to start development:
- Fork the repo on GitHub if you haven't already
- Clone your fork locally
- Create a feature branch
- Work on your changes
- Create a Draft Pull Request (PR)
- When ready, mark your PR as "ready for review".
Rules
- Follow the pattern of what you already see in the code.
- Coding style.
- Try to package new functionality/components into libraries that have nicely defined interfaces.
- Package new functionality into classes or refactor existing functionality into a class as you extend the code.
- When adding new classes/methods/changing existing code, add new unit tests or update the existing tests.
GitHub Workflow
- Before starting to work on a fix/feature, make sure there is an open issue to track the work.
- Add the
In progresslabel to the issue, if not already present. Also add aCost-Small/Medium/Largeestimate and make sure all appropriate labels are set. - If you are a community contributor, you will not be able to add labels to the issue; in that case just add a comment saying that you have started work on the issue and try to give an estimate for the delivery date.
- If the work item has a medium/large cost, using the markdown task list, list each sub item and update the list with a check mark after completing each sub item.
- When opening a PR, follow the PR template.
- When you'd like the team to take a look (even if the work is not yet fully complete) mark the PR as 'Ready For Review' so that the team can review your work and provide comments, suggestions, and request changes. It may take several cycles, but the end result will be solid, testable, conformant code that is safe for us to merge.
- When the PR is approved, let the owner of the PR merge it. For community contributions, the reviewer who approved the PR can also merge it.
- Use the
Squash and mergeoption to merge a PR. If you don't want to squash it because there are logically different commits, useRebase and merge. - Close issues automatically when referenced in a PR. You can use closing keywords in the body of the PR to have GitHub automatically link your PR to the issue.
Compiling PowerToys
Prerequisites for Compiling PowerToys
- Windows 10 April 2018 Update (version 1803) or newer
- Visual Studio Community/Professional/Enterprise 2022 17.4 or newer
- A local clone of the PowerToys repository
- Enable long paths in Windows (see Enable Long Paths for details)
Automated Setup (Recommended)
Run the setup script to automatically configure your development environment:
.\tools\build\setup-dev-environment.ps1
This script will:
- Enable Windows long path support (requires administrator privileges)
- Enable Windows Developer Mode (requires administrator privileges)
- Guide you through installing required Visual Studio components from
.vsconfig - Initialize git submodules
Run with -Help to see all available options:
.\tools\build\setup-dev-environment.ps1 -Help
Manual Setup
If you prefer to set up manually, follow these steps:
Install Visual Studio dependencies
- Open the
PowerToys.slnxfile. - If you see a dialog that says
install extra componentsin the solution explorer pane, clickinstall
Alternatively, import the .vsconfig file from the repository root using Visual Studio Installer to install all required workloads.
Get Submodules to compile
We have submodules that need to be initialized before you can compile most parts of PowerToys. This should be a one-time step.
- Open a terminal
- Navigate to the folder you cloned PowerToys to.
- Run
git submodule update --init --recursive
Compiling Source Code
Using Visual Studio
- Open
PowerToys.slnxin Visual Studio. - In the
Solutions Configurationdrop-down menu selectReleaseorDebug. - From the
Buildmenu chooseBuild Solution, or press Control+Shift+b on your keyboard. - The build process may take several minutes depending on your computer's performance. Once it completes, the PowerToys binaries will be in your repo under
x64\Release\.- You can run
x64\Release\PowerToys.exedirectly without installing PowerToys, but some modules (i.e. PowerRename, ImageResizer, File Explorer extension etc.) will not be available unless you also build the installer and install PowerToys.
- You can run
Using Command Line
You can also build from the command line using the provided scripts in tools\build\:
# Build the full solution (auto-detects platform)
.\tools\build\build.ps1
# Build with specific configuration
.\tools\build\build.ps1 -Platform x64 -Configuration Release
# Build only essential projects (runner + settings) for faster iteration
.\tools\build\build-essentials.ps1
# Build everything including the installer (Release only)
.\tools\build\build-installer.ps1
Compile the installer
Our installer is two parts, an EXE and an MSI. The EXE (Bootstrapper) contains the MSI and handles more complex installation logic.
- The EXE installs all prerequisites and installs PowerToys via the MSI. It has additional features such as the installation flags (see below).
- The MSI installs the PowerToys binaries.
The installer can only be compiled in Release mode; steps 1 and 2 must be performed before the MSI can be compiled.
- Compile
PowerToys.slnx. Instructions are listed above. - Compile
BugReportTool.slntool. Path from root:tools\BugReportTool\BugReportTool.sln(details listed below) - Compile
StylesReportTool.slntool. Path from root:tools\StylesReportTool\StylesReportTool.sln(details listed below) - Compile
PowerToysSetup.slnxPath from root:installer\PowerToysSetup.slnx(details listed below)
See Installer for more details on building and debugging the installer.
How to create new PowerToys
See the instructions on how to install the PowerToys Module project template.
Specifications for the PowerToys settings API.