Philosophy
PowerToys follows a pragmatic approach to coding style:
When modifying existing code : Follow the existing style as closely as possible
When writing new code : Follow Modern C++ and C# best practices
When refactoring : Apply modern patterns and reference language guidelines
Consistency within a file or module is more important than strict adherence to global rules. Make the code readable and maintainable.
C++ Style
Core Guidelines
Follow the C++ Core Guidelines for modern C++ development.
Key principles:
Use RAII (Resource Acquisition Is Initialization)
Prefer std::unique_ptr and std::shared_ptr over raw pointers
Use const and constexpr where applicable
Avoid manual memory management
Use standard library algorithms and containers
PowerToys uses ClangFormat for automatic C++ code formatting.
Automatic formatting:
Format document: Ctrl+K, Ctrl+D
Format selection: Ctrl+K, Ctrl+F
Enable automatic formatting:
Tools > Options > Text Editor > C/C++ > Code Style > Formatting
Check “Automatically format on paste”
Check “Automatically format completed statement on ;“
Format modified files automatically:
# Format all modified files
.\src\codeAnalysis\format_sources.ps1
Requirements:
Run from “Native Tools Command Prompt for VS”
Or ensure clang-format.exe is in %PATH%
Script uses Git to find modified files
Manual formatting:
# Format specific file
clang - format - i path\to\file.cpp
# Format with style from .clang-format
clang - format - style = file - i path\to\file.cpp
Configuration file: src/.clang-format
Key formatting rules:
BasedOnStyle : LLVM
IndentWidth : 4
TabWidth : 4
UseTab : Never
ColumnLimit : 120
PointerAlignment : Left
BreakBeforeBraces : Allman
C++ Naming Conventions
Element Convention Example Classes PascalCase ColorPicker, WindowManagerFunctions camelCase or snake_case getWindowRect(), init_logger()Variables camelCase or snake_case currentWindow, window_rectConstants UPPER_CASE MAX_BUFFER_SIZENamespaces lowercase fancyzones, powerrenameextMember variables m_ prefix (optional) m_windowHandle, m_settings
C++ Best Practices
Modern C++ Features
Prefer smart pointers:
// Good
auto window = std :: make_unique < Window >();
std ::shared_ptr < Settings > settings = GetSettings ();
// Avoid
Window * window = new Window ();
delete window;
Use auto for type deduction:
// Good
auto rect = GetWindowRect (hwnd);
auto & settings = GetSettings ();
// Avoid
RECT rect = GetWindowRect (hwnd);
Range-based for loops:
// Good
for ( const auto & item : collection)
{
ProcessItem (item);
}
// Avoid
for ( size_t i = 0 ; i < collection . size (); i ++ )
{
ProcessItem ( collection [i]);
}
String Handling
// Prefer std::wstring for Windows APIs
std ::wstring windowTitle = L"PowerToys" ;
// Use string literals
using namespace std :: string_literals ;
auto message = L"Error: " s + errorDetails;
// Avoid C-style strings when possible
// Use std::wstring instead of wchar_t*
Error Handling
// Use exceptions for exceptional cases
try
{
auto result = ProcessInput (input);
}
catch ( const std ::exception & ex)
{
Logger :: error ( "Processing failed: {}" , ex . what ());
}
// Use return codes for expected failures
if ( ! ValidateInput (input))
{
return ERROR_INVALID_PARAMETER;
}
Include Order
// 1. Precompiled header (if used)
#include "pch.h"
// 2. Corresponding header file
#include "MyClass.h"
// 3. C system headers
#include <windows.h>
// 4. C++ standard library headers
#include <string>
#include <vector>
#include <memory>
// 5. Third-party library headers
#include <json.hpp>
// 6. Project headers
#include "common/utils.h"
#include "Settings.h"
C# Style
Naming Conventions
Element Convention Example Classes PascalCase ColorPicker, SettingsViewModelInterfaces IPascalCase IModule, ISettingsMethods PascalCase GetWindowRect(), ProcessInput()Properties PascalCase WindowTitle, IsEnabledFields (private) _camelCase _windowHandle, _settingsParameters camelCase windowHandle, inputTextLocal variables camelCase currentWindow, resultConstants PascalCase MaxBufferSize, DefaultTimeoutEnums PascalCase WindowState.Maximized
C# Best Practices
Nullable Reference Types
PowerToys enables nullable reference types:
// Good - explicit nullability
public string ? GetWindowTitle ( Window ? window )
{
if ( window == null )
{
return null ;
}
return window . Title ;
}
// Use null-forgiving operator when you know it's not null
var title = GetWindowTitle ( window ) ! ;
Properties vs Fields
// Good - use properties for public members
public class Settings
{
public string ModuleName { get ; set ; }
public bool IsEnabled { get ; set ; }
private string _internalState ;
}
// Use auto-properties when possible
public string Name { get ; set ; } = "Default" ;
LINQ and Modern C#
// Good - use LINQ for collections
var activeModules = modules
. Where ( m => m . IsEnabled )
. OrderBy ( m => m . Name )
. ToList ();
// Pattern matching
if ( obj is Settings settings && settings . IsEnabled )
{
ApplySettings ( settings );
}
// Switch expressions
var description = module switch
{
"FancyZones" => "Window manager" ,
"PowerRename" => "Bulk rename tool" ,
_ => "Unknown module"
};
Async/Await
// Good - async all the way
public async Task < Settings > LoadSettingsAsync ()
{
var json = await File . ReadAllTextAsync ( settingsPath );
return JsonSerializer . Deserialize < Settings >( json );
}
// Use ConfigureAwait(false) in library code
var result = await ProcessAsync (). ConfigureAwait ( false );
IDisposable Pattern
public class ResourceManager : IDisposable
{
private bool _disposed = false ;
private FileStream ? _stream ;
public void Dispose ()
{
Dispose ( true );
GC . SuppressFinalize ( this );
}
protected virtual void Dispose ( bool disposing )
{
if ( ! _disposed )
{
if ( disposing )
{
// Dispose managed resources
_stream ? . Dispose ();
}
_disposed = true ;
}
}
}
Visual Studio’s default C# formatting is generally acceptable.
Key settings:
Indentation: 4 spaces (no tabs)
Brace style: Allman (braces on new line)
Line length: Aim for 120 characters or less
Example:
public class Example
{
public void Method ( string parameter )
{
if ( condition )
{
DoSomething ();
}
else
{
DoSomethingElse ();
}
}
}
XAML Style
XamlStyler
PowerToys uses XamlStyler for XAML formatting.
Install XamlStyler
Visual Studio Extension
In Visual Studio:
Format on save (if enabled in XamlStyler options)
Manual format: Right-click in XAML editor > Format Document
From command line:
# Format all XAML files
.\.pipelines\applyXamlStyling.ps1 - Main
XAML Conventions
Element ordering:
<Button
x:Name="SaveButton"
Grid.Row="1"
Grid.Column="2"
Width="100"
Height="32"
Margin="8,0,0,0"
Content="Save"
Click="SaveButton_Click" />
Use resource strings:
<!-- Good - localizable -->
<TextBlock Text="{x:Bind ViewModel.Title}" />
<Button x:Uid="SaveButton" Content="Save" />
<!-- Avoid - hardcoded strings -->
<Button Content="Save" />
Naming:
x:Name in PascalCase: MainGrid, SettingsPanel
x:Uid for localization: ModuleName_SettingName
Resource Strings and Localization
Resource String Naming
Pattern: <ModuleName>_<Context>_<Element>
Examples:
FancyZones_Settings_EnableZones
ColorPicker_OOBE_Description
PowerRename_Error_InvalidPattern
Using Resource Strings
In XAML:
<TextBlock x:Uid="FancyZones_Settings_Title" />
<!-- In Resources.resw -->
<data name="FancyZones_Settings_Title.Text" xml:space="preserve">
<value>FancyZones Settings</value>
</data>
In C#:
var resourceLoader = ResourceLoader . GetForViewIndependentUse ();
string title = resourceLoader . GetString ( "FancyZones_Settings_Title" );
Never submit PRs that modify localized strings in languages other than English. Localization is handled by Microsoft’s internal localization team.
Good comments explain WHY:
// Delay required for WinAppDriver to stabilize after window creation
Sleep ( 500 );
// Windows 10 SDK bug workaround: CoCreateInstance fails without explicit apartment initialization
CoInitialize ( nullptr );
Poor comments explain WHAT (code already shows this):
// Bad - obvious from code
count ++ ; // Increment count
XML Documentation (C#)
/// < summary >
/// Processes the input string and returns the formatted result.
/// </ summary >
/// < param name = "input" > The input string to process. </ param >
/// < returns > The processed string, or null if input is invalid. </ returns >
/// < exception cref = "ArgumentNullException" > Thrown when input is null. </ exception >
public string ? ProcessInput ( string input )
{
// Implementation
}
/**
* @brief Retrieves the window rectangle.
* @param hwnd Handle to the window.
* @return The window rectangle, or empty rect if hwnd is invalid.
*/
RECT GetWindowRect ( HWND hwnd );
Pull Request Guidelines
PR Checklist
Before submitting a PR:
Code Review Expectations
Reviewers will check for:
Code readability and maintainability
Proper error handling
Memory management (C++ leaks, C# disposable patterns)
Thread safety for async code
Security considerations (input validation, injection attacks)
Performance implications
Consistency with existing patterns
Before Opening PR
Format your code:
# C++ files
.\src\codeAnalysis\format_sources.ps1
# XAML files
.\.pipelines\applyXamlStyling.ps1 - Main
Build successfully:
.\tools\build\build.ps1 - Configuration Release
Run tests:
Test Explorer: Run all tests
Verify no regressions
Review changes:
Remove debug code
Remove commented-out code
Check for unintended changes
Project-Specific Guidelines
Settings Integration
Settings JSON structure:
public class ModuleSettings : BasePTModuleSettings
{
public ModuleSettings ()
{
Name = "ModuleName" ;
Version = "1.0" ;
}
public ModuleProperties Properties { get ; set ; } = new ModuleProperties ();
}
public class ModuleProperties
{
public bool IsEnabled { get ; set ; } = true ;
public string HotKey { get ; set ; } = "Win+Shift+M" ;
}
Logging Standards
C++ logging:
#include <common/logger/logger.h>
Logger :: info ( "Module initialized" );
Logger :: warn ( "Configuration issue: {}" , details);
Logger :: error ( "Failed to process: {}" , errorMessage);
C# logging:
using ManagedCommon ;
Logger . LogInfo ( "Module initialized" );
Logger . LogWarning ( "Configuration issue" );
Logger . LogError ( "Failed to process" , exception );
Logging principles:
Log errors and warnings always
Log info for important operations
Use debug/trace sparingly (disabled by default)
Include context in log messages
Don’t log sensitive information (passwords, tokens, PII)
Telemetry
C++ telemetry:
#include <common/Telemetry/trace.h>
Trace :: ModuleName :: Enable ( true );
C# telemetry:
using PowerToys . Telemetry ;
PowerToysTelemetry . Log . WriteEvent ( new ModuleEnabledEvent ());
All telemetry respects user privacy settings. Users can disable telemetry in PowerToys Settings.
Static Analysis
PowerToys uses Visual Studio’s code analysis:
For C++:
Configuration: CppRuleSet.ruleset
Properties: Cpp.Build.props
For C#:
Built-in Roslyn analyzers
Configuration in .editorconfig
Build Properties
Key build properties:
Directory.Build.props - Shared properties for all projects
Directory.Build.targets - Shared targets
Directory.Packages.props - Central package version management
Additional Resources
External Style Guides
PowerToys Documentation
Next Steps
Building Build PowerToys from source
Debugging Debug PowerToys effectively
Testing Write tests for your code
Creating New Utility Create a new PowerToys utility