Install pywinauto with `pip install pywinauto`, then connect to a running application by title: `from pywinauto.application import Application; app = Application(backend='uia').connect(title_re='.*Notepad.*')` — use `backend='uia'` for modern apps and `backend='win32'` for legacy apps.
Launch a new application: `app = Application(backend='uia').start('notepad.exe')` — pywinauto waits for the main window to appear before returning.
Retrieve a window or dialog: `dlg = app.window(title_re='.*Notepad.*')` then access controls: `dlg.Edit.type_keys('Hello, world!', with_spaces=True)` — control wrappers are resolved lazily by control type or name.
Click buttons and menu items: `dlg.button('OK').click()` or navigate menus with `dlg.menu_select('File->Save As')` which handles the full menu chain.
Inspect the application's control tree at runtime with `dlg.print_control_identifiers()` — this prints all reachable controls with their identifiers, helping you write correct selector strings.
Known gotchas
The `uia` and `win32` backends expose different APIs and have different capabilities. If a control is not found with one backend, try the other — some older controls only expose a Win32 interface and will not appear in the UIA tree.
pywinauto uses fuzzy matching for control names by default, which can match the wrong control if multiple controls have similar names. Use `found_index` or more specific attribute combinations when name matching is ambiguous.
Applications that run with elevated privileges (UAC elevation) cannot be automated by a non-elevated Python process — pywinauto will fail to connect or control such windows. Either run your Python script elevated or ensure the target application does not require elevation.
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp