Introduction to Windows Shell Programming

Overview

The Windows Shell provides the graphical user interface for Windows, including the desktop, taskbar, Start menu, and file Explorer. Programming the shell lets you extend or customize these elements, create new user experiences, and integrate tightly with the operating system.

Getting Started

To begin developing shell extensions, you need:

  • Visual Studio 2022 or later
  • Windows SDK
  • Knowledge of COM and C++ (or C# with .NET COM interop)
  • Administrator rights for registration

Create a new Win32 Project in Visual Studio and select DLL as the output type.

Core Concepts

COM Interfaces

Shell extensions are implemented as COM objects. Common interfaces include:

  • IShellExtInit – initialization of the extension
  • IContextMenu – add custom commands to context menus
  • IShellIconOverlayIdentifier – custom overlay icons
  • IPropertyStore – retrieve or store property values

Registration

Extensions are registered in the Windows Registry under HKEY_CLASSES_ROOT\CLSID and associated with file types or shell locations.

Sample Code: Simple Context Menu Extension (C++)

#include <windows.h>
#include <shlobj.h>
#include <strsafe.h>

class ATL_NO_VTABLE CSimpleMenu :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CSimpleMenu, &CLSID_SimpleMenu>,
    public IContextMenu,
    public IShellExtInit
{
public:
    CSimpleMenu() : m_pszFolder(nullptr) {}
    DECLARE_NO_REGISTRY()
    BEGIN_COM_MAP(CSimpleMenu)
        COM_INTERFACE_ENTRY(IContextMenu)
        COM_INTERFACE_ENTRY(IShellExtInit)
    END_COM_MAP()

    // IShellExtInit
    STDMETHODIMP Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
    {
        m_pszFolder = nullptr;
        if (pidlFolder)
            SHGetPathFromIDList(pidlFolder, m_pszFolder);
        return S_OK;
    }

    // IContextMenu
    STDMETHODIMP QueryContextMenu(HMENU hMenu, UINT indexMenu,
        UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
    {
        InsertMenu(hMenu, indexMenu, MF_STRING | MF_BYPOSITION,
            idCmdFirst, L"&My Sample Command");
        return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 1);
    }

    STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pInfo)
    {
        if (HIWORD(pInfo->lpVerb))
            return E_FAIL;
        MessageBox(pInfo->hwnd, L"Sample command invoked!", L"Shell Extension", MB_OK);
        return S_OK;
    }

    STDMETHODIMP GetCommandString(UINT_PTR idCmd,
        UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
    {
        return E_NOTIMPL;
    }

private:
    wchar_t m_szFolder[MAX_PATH];
};

OBJECT_ENTRY_AUTO(__uuidof(CSimpleMenu), CSimpleMenu)

Build the DLL, register it with regsvr32 MyShellExt.dll, and refresh Explorer. The new menu item appears on right‑click for all files.

Additional Resources