# Developing Shell Extensions for File Explorer Context Menus in PowerToys: A Complete Guide

> Learn to develop File Explorer context menu shell extensions in PowerToys. This guide covers using IExplorerCommand and COM objects for dynamic sub-menus in the New+ module.

- Repository: [Microsoft/PowerToys](https://github.com/microsoft/PowerToys)
- Tags: how-to-guide
- Published: 2026-02-25

---

**PowerToys implements File Explorer context menu extensions using the Windows Explorer Command API (`IExplorerCommand`), creating hierarchical sub-menus through COM objects that dynamically enumerate template items in the New+ module.**

The **New+** feature in microsoft/PowerToys demonstrates advanced shell extension development by adding dynamic context menus to Windows File Explorer. This implementation showcases how to build scalable, settings-aware context menu extensions using modern Windows APIs. Understanding this architecture provides a blueprint for developing shell extensions for File Explorer context menus in PowerToys or standalone Windows applications.

## Architecture of the Explorer Command API Implementation

PowerToys’s New+ shell extension follows a three-layer COM architecture based on the **Explorer Command API**.

**Layer 1: Top-level command** ([`shell_context_menu.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_menu.cpp))
Implements `IExplorerCommand` to expose the root "New+" menu item. Key methods include `GetTitle` for localization, `GetIcon` for the menu icon, and `GetFlags` returning `ECF_HASSUBCOMMANDS` to indicate sub-menu availability.

**Layer 2: Sub-command enumerator** ([`shell_context_sub_menu.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_sub_menu.cpp))
Implements `IEnumExplorerCommand` to dynamically generate the menu list. This scans the user's *New+ Templates* folder and instantiates individual commands for each template file.

**Layer 3: Individual template commands** ([`shell_context_sub_menu_item.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_sub_menu_item.cpp))
Each template item implements `IExplorerCommand` with `GetTitle`, `GetIcon`, and `Invoke` methods that execute the copy operation when selected.

## Core Components for Developing File Explorer Context Menu Extensions

### Top-Level Menu Command ([`shell_context_menu.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_menu.cpp))

Located at [`src/modules/NewPlus/NewShellExtensionContextMenu/shell_context_menu.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/NewPlus/NewShellExtensionContextMenu/shell_context_menu.cpp), this file contains the `shell_context_menu` class implementing the root menu item.

The class exposes four critical methods:

- **`GetTitle`** – Returns the localized string "New+" from resources
- **`GetIcon`** – Resolves the icon path via `utilities::get_new_icon_resource_filepath`
- **`GetState`** – Queries `NewSettingsInstance().GetEnabled()` to hide the menu when the feature is disabled
- **`EnumSubCommands`** – Instantiates `shell_context_sub_menu` to provide the sub-menu enumerator

### Dynamic Sub-Menu Enumeration ([`shell_context_sub_menu.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_sub_menu.cpp))

The `shell_context_sub_menu` class in [`shell_context_sub_menu.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_sub_menu.cpp) implements `IEnumExplorerCommand` to provide dynamic content.

During construction, it:

1. Calls `utilities::get_new_template_folder_location()` to locate user templates
2. Iterates through template definitions
3. Creates `shell_context_sub_menu_item` instances stored in `explorer_menu_item_commands`
4. Appends static items: a separator (`separator_context_menu_item`) and "Open templates" entry (`template_folder_context_menu_item`)

The class implements standard enumerator methods: `Next`, `Reset`, and `Skip`.

### Per-Template Command Execution ([`shell_context_sub_menu_item.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_sub_menu_item.cpp))

Individual menu items are handled by `shell_context_sub_menu_item` in [`shell_context_sub_menu_item.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_sub_menu_item.cpp).

Each instance:

- Formats display titles via `GetTitle`, applying settings like hiding extensions or leading digits
- Resolves template-specific icons through `GetIcon`
- Executes `Invoke` to call `newplus::utilities::copy_template()`, copying template contents to the selected folder

## Integrating Settings and Utilities

### Settings Integration ([`settings.cpp`](https://github.com/microsoft/PowerToys/blob/main/settings.cpp))

The extension respects PowerToys configuration through [`settings.cpp`](https://github.com/microsoft/PowerToys/blob/main/settings.cpp). The `NewSettingsInstance()` singleton reads JSON configuration to determine:

- Whether the feature is enabled (affects `GetState`)
- Display preferences like hiding file extensions or leading digits in template names

### Utility Layer ([`new_utilities.cpp`](https://github.com/microsoft/PowerToys/blob/main/new_utilities.cpp))

Helper functions in [`new_utilities.cpp`](https://github.com/microsoft/PowerToys/blob/main/new_utilities.cpp) handle filesystem operations:

- `copy_template()` – Performs the actual file copy from template folder to destination
- `open_template_folder()` – Launches the templates directory when users select "Open templates"
- `create_folder_if_not_exist()` – Ensures the template directory exists before enumeration

## COM Registration and Module Entry Point

Registration occurs in [`powertoys_module.cpp`](https://github.com/microsoft/PowerToys/blob/main/powertoys_module.cpp), which declares the COM class under the **ExplorerCommand** CLSID. The PowerToys module loader ensures the DLL loads when Explorer constructs the context menu, registering the extension with Windows Explorer's command infrastructure.

## Practical Implementation: Adding a Custom Template Item

Below is a minimal example adapted from [`template_folder.cpp`](https://github.com/microsoft/PowerToys/blob/main/template_folder.cpp) showing how to programmatically add a template item within the sub-menu enumerator:

```cpp
// Resolve the template folder location
const std::filesystem::path templateRoot = utilities::get_new_template_folder_location();
utilities::create_folder_if_not_exist(templateRoot);

// Create a template item manually (typically loaded from JSON)
auto myProjectTemplate = std::make_unique<template_item>();
myProjectTemplate->set_name(L"My Project");
myProjectTemplate->set_icon(L"myproject.ico");
myProjectTemplate->set_content(L"// My C++ project skeleton");

// Add to the command list for enumeration
explorer_menu_item_commands.push_back(
    Make<shell_context_sub_menu_item>(myProjectTemplate.get(), site_of_folder));

```

When selected, `shell_context_sub_menu_item::Invoke` forwards to `newplus::utilities::copy_template()`, creating the file at the target location.

## Summary

- **PowerToys uses `IExplorerCommand`** to implement File Explorer context menu extensions, not legacy context menu handlers
- **Three-layer architecture**: Top-level command ([`shell_context_menu.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_menu.cpp)), enumerator ([`shell_context_sub_menu.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_sub_menu.cpp)), and item commands ([`shell_context_sub_menu_item.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_sub_menu_item.cpp))
- **Dynamic enumeration**: The extension scans `%LOCALAPPDATA%\Microsoft\PowerToys\New+\Templates` to build menus at runtime
- **Settings-aware**: [`settings.cpp`](https://github.com/microsoft/PowerToys/blob/main/settings.cpp) integrates with PowerToys JSON configuration to control visibility and formatting
- **COM registration**: [`powertoys_module.cpp`](https://github.com/microsoft/PowerToys/blob/main/powertoys_module.cpp) registers the extension using the ExplorerCommand CLSID for automatic loading by Explorer

## Frequently Asked Questions

### What Windows API does PowerToys use for File Explorer context menus?

PowerToys implements the **Explorer Command API** using `IExplorerCommand` and `IEnumExplorerCommand` interfaces. This modern API, used in the New+ module's [`shell_context_menu.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_menu.cpp), provides better performance and reliability than legacy context menu shell extensions.

### How does the New+ extension dynamically populate its sub-menu?

The `shell_context_sub_menu` class in [`shell_context_sub_menu.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_sub_menu.cpp) implements `IEnumExplorerCommand::Next` to enumerate template files from the user's *New+ Templates* folder. It creates a `shell_context_sub_menu_item` for each template, plus static entries for the separator and "Open templates" command.

### Where does PowerToys store the template files for the New+ menu?

Templates are stored in the user's local application data folder, resolved via `utilities::get_new_template_folder_location()` in [`new_utilities.cpp`](https://github.com/microsoft/PowerToys/blob/main/new_utilities.cpp). The path typically resolves to `%LOCALAPPDATA%\Microsoft\PowerToys\New+\Templates`, where the extension reads JSON or text definitions.

### How can I disable the New+ context menu without uninstalling PowerToys?

The extension checks `NewSettingsInstance().GetEnabled()` in `shell_context_menu::GetState` (located in [`shell_context_menu.cpp`](https://github.com/microsoft/PowerToys/blob/main/shell_context_menu.cpp)). When disabled in PowerToys Settings, the method returns `ECS_HIDDEN`, preventing the menu from appearing in File Explorer context menus.