Of course! uiautomation is a powerful and popular Python library for automating the Windows Graphical User Interface (GUI). It's essentially a wrapper around the UI Automation API provided by Windows, making it accessible and easy to use for Python developers.

Here's a comprehensive guide covering everything you need to know to get started with uiautomation.
What is uiautomation?
uiautomation is a Python module that allows you to programmatically interact with Windows applications. You can use it to:
- Find UI elements: Buttons, text boxes, menus, list items, etc.
- Get information from UI elements: Text content, properties, and states (e.g., is a button enabled?).
- Interact with UI elements: Click buttons, type text into fields, select items from lists, and more.
- Control windows: Move, resize, minimize, maximize, and close application windows.
- Automate repetitive tasks: Automate data entry, software testing, or any other GUI-based workflow.
A key feature of uiautomation is that it uses UIA (UI Automation), the modern accessibility framework in Windows. This makes it more reliable for newer applications (like those built with WPF, UWP, or WinForms) compared to older libraries that rely on older APIs like Win32 or SendKeys.
Installation
First, you need to install the library. It's available on PyPI.

pip install uiautomation
Core Concepts
To use uiautomation, you need to understand three main concepts:
- Element: Any item on the screen, from the entire desktop window down to a single pixel. Elements have a tree-like structure (parent-child relationships).
- Control Type: The type of an element (e.g.,
Button,Edit,Text,List,MenuItem). This is the most common way to find elements. - Properties: Attributes of an element, such as its
Name,AutomationId, orControlType. You can use these properties to uniquely identify an element.
How to Find UI Elements
This is the most critical part of GUI automation. uiautomation offers several methods to find elements, ranging from simple to more specific.
The Desktop (Desktop)
All UI elements are descendants of the desktop window. You start your search from here.
import uiautomation as auto
# Get the desktop element
desktop = auto.Desktop()
print(f"Desktop Name: {desktop.Name}")
Finding by Control Type (Most Common)
You can search for elements by their type (e.g., Button, Text, Edit) using methods like ButtonControl(), TextControl(), EditControl(), etc.

These methods search within a given element's children.
Example: Find all buttons on the desktop
import uiautomation as auto
desktop = auto.Desktop()
# Find all Button controls under the desktop
buttons = desktop.ButtonControl()
# The method returns the first match. To get all, you need to use a loop or a more advanced search.
# Let's find a button with a specific name.
ok_button = desktop.ButtonControl(SubName="OK") # SubName is a partial match on the element's Name
if ok_button:
print(f"Found 'OK' button: {ok_button.Name}")
Finding by Search Properties (More Precise)
For more control, you can use the generic FindAll() or FindFirst() methods, which allow you to specify a dictionary of properties to match.
ControlType: The type of control.Name: The name of the control.AutomationId: A stable identifier for the control (very useful!).ClassName: The underlying Windows class name.
Example: Find a specific text box
Let's say we want to find the search bar in the Windows Calculator.
import uiautomation as auto
import time
# Open Calculator (you might need to do this manually or with another script)
# For this example, let's assume it's already open.
desktop = auto.Desktop()
# Find the Calculator window first
# We search for a window with the name "Calculator"
calculator_window = desktop.WindowControl(Name="Calculator")
if not calculator_window.Exists(3): # Check if it exists for 3 seconds
print("Calculator window not found. Please open it.")
exit()
# Now, find the text display inside the calculator window
# It's a TextControl with AutomationId "CalculatorResults"
display_text = calculator_window.TextControl(AutomationId="CalculatorResults")
if display_text:
print(f"Found display: '{display_text.Name}' with text: '{display_text.GetWindowText()}'")
else:
print("Could not find the calculator display.")
Advanced Search: Tree Walker
For complex UI structures, TreeWalker gives you fine-grained control to traverse the element tree manually. This is useful when other methods fail.
import uiautomation as auto
desktop = auto.Desktop()
walker = auto.TreeWalker(auto.ConditionControlType(auto.ControlType.Window))
# Get the first child of the desktop (which is a window)
first_window = walker.GetNextSibling(desktop)
if first_window:
print(f"First window found: {first_window.Name}")
Common UI Actions and Information
Once you have a UI element, you can perform various actions and get information from it.
| Method/Property | Description | Example |
|---|---|---|
Click() |
Simulates a mouse click. | ok_button.Click() |
SendKeys(keys) |
Sends keyboard input to an element (e.g., a text box). | edit_box.SendKeys("Hello World") |
GetWindowText() |
Gets the text content of an element. | print(text_box.GetWindowText()) |
Name |
Gets the Name property of the element. |
print(button.Name) |
Enabled |
Checks if the element is enabled. | if button.Enabled: ... |
Exists(timeout) |
Checks if the element still exists on the screen. Can wait for a timeout. | if my_button.Exists(5): ... (wait up to 5 seconds) |
SetFocus() |
Sets the keyboard focus to the element. | edit_box.SetFocus() |
GetBoundingRectangle() |
Gets the screen coordinates (x, y, width, height) of the element. | rect = my_button.GetBoundingRectangle() |
Complete Example: Automating Notepad
Let's put it all together in a practical example. We will:
- Open Notepad.
- Type a sentence.
- Save the file with a specific name.
- Close Notepad.
Note: To open Notepad, you can use os.system or subprocess, but this is OS-dependent. For a pure uiautomation script, you would need to open it manually before running the script.
import uiautomation as auto
import time
import os
# --- Configuration ---
APP_NAME = "Untitled - Notepad"
SAVE_BUTTON_NAME = "Save"
FILE_NAME_EDIT_ID = "File name:"
SAVE_DIALOG_NAME = "Save As"
def main():
# 1. Find the Notepad window
print("Looking for Notepad window...")
notepad_window = auto.Desktop().WindowControl(Name=APP_NAME)
if not notepad_window.Exists(3):
print(f"Error: Could not find '{APP_NAME}' window. Please open Notepad.")
return
print(f"Found Notepad window: {notepad_window.Name}")
# 2. Type text into the editor
# The main text area in Notepad is an Edit control.
# We can find it by its ControlType and its position relative to the window.
edit_control = notepad_window.EditControl()
if not edit_control.Exists():
print("Error: Could not find the text area in Notepad.")
return
print("Typing text into Notepad...")
edit_control.SetFocus()
edit_control.SendKeys("Hello from uiautomation! This is a test.")
time.sleep(1) # Pause to see the typing
# 3. Save the file
print("Saving the file...")
# Use the hotkey Alt + F to open the File menu
auto.SendKeys('{ALT}f')
time.sleep(0.5)
# Find the 'Save' menu item and click it
# We search within the menu popup, which is a Menu control
save_menu_item = auto.MenuControl().MenuItemControl(Name=SAVE_BUTTON_NAME)
if save_menu_item.Exists():
save_menu_item.Click()
else:
print("Error: Could not find the 'Save' menu item.")
return
time.sleep(1) # Wait for the "Save As" dialog to appear
# 4. Handle the "Save As" dialog
print("Handling 'Save As' dialog...")
save_dialog = auto.Desktop().WindowControl(Name=SAVE_DIALOG_NAME)
if not save_dialog.Exists():
print("Error: 'Save As' dialog did not appear.")
return
# Find the file name edit box and type the name
file_name_edit = save_dialog.EditControl(AutomationId=FILE_NAME_EDIT_ID)
if file_name_edit.Exists():
file_name_edit.SetFocus()
file_name_edit.SendKeys("my_test_file.txt{ENTER}") # Type name and press Enter
print("File saved as 'my_test_file.txt'")
else:
print("Error: Could not find the file name edit box in the 'Save As' dialog.")
# 5. Close Notepad
print("Closing Notepad...")
notepad_window.Close()
# Handle the "Do you want to save?" dialog that might appear
time.sleep(1)
save_dialog = auto.Desktop().WindowControl(Name="Notepad")
if save_dialog.Exists():
save_dialog.ButtonControl(SubName="Don't Save").Click()
if __name__ == "__main__":
main()
Tips and Best Practices
- Use
AutomationIdwhenever possible: It's the most stable way to find elements, as it doesn't change with localization (unlikeName) or minor UI updates. - Be Patient: GUI operations are not instantaneous. Always add small
time.sleep()delays or use theExists(timeout)method to wait for elements to appear or become ready. - Use
SubNamefor Partial Matches: If an element's full name is dynamic (e.g., "Untitled - Notepad"), useSubName="Notepad"to find it. - Inspect UI Elements: The best way to find the right
ControlType,Name, orAutomationIdis to use a tool. Inspect.exe is a free tool from Microsoft that comes with the Windows SDK. It allows you to point at any UI element and see all its properties. - Start Broad, Then Narrow: First, find the main window. Then, search for elements within that window. This makes your scripts more robust.
- Handle Errors: Always check if an element was found using
if element.Exists()before trying to interact with it. This prevents your script from crashing.
