Enforces RAII patterns for Windows resource management using the Windows Implementation Library.

Install

mkdir -p .claude/skills/wil-raii && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15871" && unzip -o skill.zip -d .claude/skills/wil-raii && rm skill.zip

Installs to .claude/skills/wil-raii

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Windows Implementation Library (WIL) RAII patterns for managing Windows resources. Use when creating, managing, or cleaning up Windows handles like HICON, HWND, HBITMAP, HDC, COM objects, or any GDI resources.
209 chars✓ has a “when” trigger
Advanced

Key capabilities

  • Manage HICON resources with `wil::unique_hicon`
  • Manage HWND resources with `wil::unique_hwnd`
  • Manage COM objects with `wil::com_ptr<T>`
  • Handle GDI selections with `wil::SelectObject`
  • Ensure cleanup with `wil::scope_exit`

How it works

The skill provides WIL RAII wrappers and patterns to automatically manage and clean up Windows resources like handles and COM objects.

Inputs & outputs

You give it
Windows handle or resource
You get back
RAII-managed Windows resource

When to use wil-raii

  • Manage HICON or HWND
  • Clean up COM objects
  • Implement safe GDI resource management
  • Ensure auto-cleanup on exit

About this skill

WIL RAII Resource Management

CRITICAL: NO MANUAL RESOURCE CLEANUP - All Windows resources MUST use RAII wrappers. goto is prohibited; use wil::scope_exit for cleanup and common exit paths.

WIL Wrapper Reference

ResourceWIL Wrapper
HICONwil::unique_hicon
HWNDwil::unique_hwnd
HBITMAPwil::unique_hbitmap
HFONTwil::unique_any<HFONT, decltype(&::DeleteObject), ::DeleteObject>
HBRUSHwil::unique_any<HBRUSH, decltype(&::DeleteObject), ::DeleteObject>
HPENwil::unique_any<HPEN, decltype(&::DeleteObject), ::DeleteObject>
HDCwil::unique_hdc
Paintwil::unique_hdc_paint with wil::BeginPaint(hwnd, &ps)
COMwil::com_ptr<T>
Cleanupwil::scope_exit with lambda

Patterns

Member Variables

class MyWindow 
{
    wil::unique_hicon _icon;
    wil::unique_hwnd _tooltip;
    wil::unique_any<HFONT, decltype(&::DeleteObject), ::DeleteObject> _font;
};

Paint Context (auto EndPaint)

PAINTSTRUCT ps;
wil::unique_hdc_paint hdc = wil::BeginPaint(_hWnd, &ps);
FillRect(hdc.get(), &ps.rcPaint, brush);
// Automatic EndPaint on scope exit

GDI Selection (auto restore)

{
    auto oldBrush = wil::SelectObject(hdc, _brush.get());
    // Drawing...
} // Old brush automatically restored

Direct2D BeginDraw/EndDraw

{
    HRESULT hr = S_OK;
    {
        _d2dContext->BeginDraw();
        auto endDraw = wil::scope_exit([&] { hr = _d2dContext->EndDraw(); });
        // Drawing operations...
    }
    if (FAILED(hr)) { /* handle */ }
}

COM Pointers (wil::com_ptr<T>)

Use wil::com_ptr<T> for COM interface lifetimes and prefer single-step copy semantics.

// ✅ Copy (AddRef) in one step
wil::com_ptr<IFileSystem> fs = rawFs;
fs = rawFs;

// ✅ Receive an owning ref via out-param (avoids attach())
wil::com_ptr<IMuffin> muffin;
HRESULT hr = GetMuffin(muffin.put());

Avoid manual ref-counting + attach() on the same pointer:

// ❌ Two-step hazard (can leak a ref if an exception occurs between lines)
rawFs->AddRef();
fs.attach(rawFs);

Required Include

#pragma warning(push)
#pragma warning(disable: 4625 4626 5026 5027 28182)
#include <wil/resource.h>
#pragma warning(pop)

Resource Creation and Access

// Creation
_icon.reset(LoadIcon(...));
_tooltip.reset(CreateWindowExW(...));

// Access raw handle for Win32 APIs
DrawIcon(hdc, x, y, _icon.get());
SendMessageW(_tooltip.get(), WM_SETFONT, 
    reinterpret_cast<WPARAM>(_font.get()), TRUE);

// Transfer ownership
wil::unique_hbitmap bitmap(CreateCompatibleBitmap(...));
_bitmaps.emplace_back(std::move(bitmap));

// Clear resources
_bitmaps.clear();  // All HBITMAPs automatically deleted
_icon.reset();     // Old icon destroyed, set to nullptr

Destroying Owned Windows (wil::unique_hwnd)

If an HWND is owned by wil::unique_hwnd, destroy via the wrapper (do not call DestroyWindow(_hWnd.get())).

// ✅ Preferred: destroy + clear ownership
_hWnd.reset();

// ✅ Transfer ownership explicitly (rare)
HWND hwnd = _hWnd.release();
DestroyWindow(hwnd);

Menu Cleanup with scope_exit

HMENU menu = CreatePopupMenu();
auto menuCleanup = wil::scope_exit([&] { if (menu) DestroyMenu(menu); });
// Use menu...
// Automatic cleanup on scope exit

Multiple GDI Selections

{
    auto oldPen = wil::SelectObject(hdc, _pen.get());
    {
        auto oldBrush = wil::SelectObject(hdc, _brush.get());
        // Draw with pen and brush
    } // Brush restored
    // Draw with pen only
} // Pen restored

Exception: Transfer-of-Ownership

Cross-thread icon passing is acceptable when properly documented and receiver takes RAII ownership:

// Move unique_hicon across threads
wil::unique_hicon icon = ExtractOnBackgroundThread();
PostToUIThread([icon = std::move(icon)]() {
    // UI thread now owns the icon
});

PROHIBITED

goto cleanup patterns are forbidden (prefer early returns + wil::scope_exit).

// ❌ NEVER manual cleanup
DestroyIcon(_icon);
DeleteObject(font);
EndPaint(hWnd, &ps);

// ❌ NEVER destroy an owned HWND via .get()
DestroyWindow(_hWnd.get());

// ❌ NEVER raw handle with manual delete
HFONT font = CreateFontW(...);
// ... use font ...
DeleteObject(font);

// ❌ NEVER vector of raw handles
std::vector<HBITMAP> bitmaps;
for (auto bmp : bitmaps) {
    DeleteObject(bmp); // Manual cleanup loop
}

When not to use it

  • When performing manual resource cleanup
  • When using `goto` for cleanup patterns
  • When destroying an owned HWND via `.get()`

Limitations

  • Manual resource cleanup is prohibited
  • `goto` cleanup patterns are forbidden
  • Destroying an owned HWND via `.get()` is prohibited

How it compares

This skill enforces RAII wrappers for all Windows resources, eliminating manual cleanup and `goto` patterns common in traditional Win32 programming.

Compared to similar skills

wil-raii side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
wil-raii (this skill)03moNo flagsAdvanced
static-analysis56moNo flagsAdvanced
memory-safety-patterns44moNo flagsAdvanced
gdb-cli03moReviewAdvanced

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry