​uiautomation基础教程

时间:2025-11-25 05:26:16  阅读量:  分类:标签:

uiautomation 的核心是「控件」和「定位」:

1、控件(Control):桌面应用的可交互元素(窗口、按钮、输入框、菜单等),每个控件有唯一的层级和属性。

2、控件属性(关键定位依据):

Name:控件显示文本(如按钮 “确定”、窗口标题)。

ClassName:控件类名(如输入框 Edit、按钮 Button)。

AutomationId:控件唯一标识(WPF/Qt 应用常用,最稳定)。

ControlType:控件类型(如 ControlType.Button、ControlType.Edit)。

3、控件层级:所有桌面控件构成树形结构(桌面 → 应用窗口 → 子控件 → ...),uiautomation 可通过层级遍历或直接定位控件。

 

要求 Python 3.6+,下载地址:https://www.python.org/downloads/,安装时勾选「Add Python to PATH」。

 

2. 安装 uiautomation 库-命令行执行以下命令(国内用户可加清华源加速):

pip install uiautomation -i https://pypi.tuna.tsinghua.edu.cn/simple

3. 必备辅助工具(定位控件用)

必须用工具查看控件属性,推荐:

Inspect.exe(微软官方,首选):支持所有 UI 框架,能查看控件的 Name、AutomationId、ControlType 等核心属性。

下载地址:https://learn.microsoft.com/zh-cn/windows/win32/winauto/inspect-exe

用法:打开后点击左上角「十字图标」,拖动到目标控件,右侧「AutomationId」「Name」「ClassName」即为定位关键信息。

 

三、第一个示例:操控记事本(Notepad)

目标:打开记事本 → 输入文本 → 保存文件 → 关闭窗口,全程用 uiautomation 实现。

步骤 1:导入库并启动记事本

先导入 uiautomation 和 subprocess(用于启动应用),启动记事本后等待窗口加载:

import uiautomation as auto
import subprocess
import time

# 启动记事本(subprocess 用于执行系统命令)
subprocess.Popen("notepad.exe")
# 等待窗口加载(1 秒足够,根据电脑性能调整)
time.sleep(1)

步骤 2:定位记事本窗口

通过「窗口标题」(Name 属性)定位记事本主窗口,uiautomation 中用 WindowControl 表示窗口控件:

# 定位记事本窗口(Name 为「无标题 - 记事本」,ClassName 为「Notepad」)
notepad_window = auto.WindowControl(
    Name="无标题 - 记事本",
    ClassName="Notepad"
)
# 激活窗口(确保在前台,避免操作失败)
notepad_window.SetActive()
time.sleep(0.5)  # 短暂休眠,确保激活成功

步骤 3:定位输入框并输入文本

记事本的输入框是「Edit」类控件(ClassName="Edit"),用 EditControl 定位,通过 SendKeys 模拟输入:

# 定位输入框(父控件是记事本窗口,ClassName="Edit")
edit_box = notepad_window.EditControl(ClassName="Edit")
# 输入文本(支持中文、特殊字符)
edit_box.SendKeys("Hello uiautomation! 这是原生 UI 自动化~")

步骤 4:通过菜单保存文件

记事本的「文件→保存」菜单是 MenuItemControl,需先定位「文件」菜单,再点击「保存」:

# 1. 定位「文件」菜单(父窗口,Name="文件",ControlType=MenuItem)
file_menu = notepad_window.MenuItemControl(Name="文件")
# 点击「文件」菜单(展开子菜单)
file_menu.Click()
time.sleep(0.5)

# 2. 定位「保存」子菜单(父菜单是「文件」,Name="保存")
save_menu = file_menu.MenuItemControl(Name="保存")
save_menu.Click()
time.sleep(1)  # 等待「另存为」窗口弹出

步骤 5:处理「另存为」窗口(输入路径 + 保存)

「另存为」窗口也是 WindowControl,需定位「文件名输入框」和「保存按钮」:

# 定位「另存为」窗口(Name="另存为",ClassName="#32770")
save_window = auto.WindowControl(Name="另存为", ClassName="#32770")
save_window.SetActive()  # 激活窗口

# 定位「文件名」输入框(ClassName="Edit",索引 1,因窗口有多个 Edit 控件)
file_name_edit = save_window.EditControl(ClassName="Edit", Index=1)
# 输入保存路径(r 表示原始字符串,避免路径转义)
file_name_edit.SendKeys(r"C:\test_uiauto.txt")
time.sleep(0.5)

# 定位「保存」按钮(Name="保存",ClassName="Button")
save_button = save_window.ButtonControl(Name="保存", ClassName="Button")
save_button.Click()
time.sleep(1)  # 等待保存完成

步骤 6:关闭记事本窗口

直接调用窗口控件的 Close() 方法关闭:

# 关闭记事本窗口
notepad_window.Close()

完整代码

import uiautomation as auto
import subprocess
import time

# 1. 启动记事本
subprocess.Popen("notepad.exe")
time.sleep(1)

# 2. 定位记事本窗口并激活
notepad_window = auto.WindowControl(Name="无标题 - 记事本", ClassName="Notepad")
notepad_window.SetActive()
time.sleep(0.5)

# 3. 输入文本
edit_box = notepad_window.EditControl(ClassName="Edit")
edit_box.SendKeys("Hello uiautomation! 这是原生 UI 自动化~")

# 4. 菜单操作:文件→保存
file_menu = notepad_window.MenuItemControl(Name="文件")
file_menu.Click()
time.sleep(0.5)
save_menu = file_menu.MenuItemControl(Name="保存")
save_menu.Click()
time.sleep(1)

# 5. 另存为窗口操作
save_window = auto.WindowControl(Name="另存为", ClassName="#32770")
save_window.SetActive()
file_name_edit = save_window.EditControl(ClassName="Edit", Index=1)
file_name_edit.SendKeys(r"C:\test_uiauto.txt")
time.sleep(0.5)
save_button = save_window.ButtonControl(Name="保存", ClassName="Button")
save_button.Click()
time.sleep(1)

# 6. 关闭窗口
notepad_window.Close()

四、核心操作详解

1. 控件定位的 3 种常用方式

uiautomation 定位控件的核心是「指定控件类型 + 筛选属性」,支持多种组合,优先级:AutomationId > Name > ClassName > Index。

(1)直接定位(已知父控件)

如果知道控件的父级(如窗口→按钮),直接通过父控件调用子控件类型:

# 父窗口 → 子按钮(已知 Name 和 ClassName)
button = 父控件.ButtonControl(Name="确定", ClassName="Button")

# 父窗口 → 输入框(已知 AutomationId,最稳定)
edit = 父控件.EditControl(AutomationId="txtUsername")

(2)通过索引定位(同类型多个控件)

如果同一父控件下有多个相同类型的控件(如多个输入框),用 Index 区分(从 0 开始):

# 定位第 2 个 Edit 控件(Index=1)
second_edit = 父控件.EditControl(Index=1)

(3)全局搜索定位(未知父控件)

如果不知道父控件,用 FindFirst 全局搜索(需指定控件类型和筛选条件):

# 全局搜索「百度一下」按钮(ControlType=Button,Name="百度一下")
baidu_button = auto.FindFirst(
    auto.PatternMatch.ControlType(auto.ControlType.Button),
    auto.PatternMatch.Name("百度一下")
)

2. 常用控件类型及操作

uiautomation 为不同类型控件提供了专属方法,以下是最常用的控件及核心操作:

控件类型 用途 核心操作 示例代码
WindowControl 应用窗口 激活、关闭、最大化、获取标题 window.SetActive() window.Close()
ButtonControl 按钮 点击、获取文本 button.Click() print(button.Name)
EditControl 输入框 输入文本、获取文本、清空 edit.SendKeys("内容") edit.GetValue()
MenuItemControl 菜单选项 点击、展开子菜单 menu.Click() submenu = menu.MenuItemControl()
CheckBoxControl 复选框 勾选、取消勾选、判断是否勾选 checkbox.SetCheck(True) checkbox.IsChecked()
ComboBoxControl 下拉框 展开、选择选项 combo.Expand() combo.SelectItem("选项1")

3. 关键辅助操作

(1)模拟键盘快捷键

用 auto.SendKeys() 模拟全局快捷键(如 Ctrl+C、Ctrl+V),支持的特殊键:

{Ctrl} {Shift} {Alt} {Enter} {Backspace} {Tab} 等

# 模拟 Ctrl+S 保存
auto.SendKeys("{Ctrl}s")

# 模拟 Ctrl+A 全选 + Ctrl+C 复制
auto.SendKeys("{Ctrl}a")
auto.SendKeys("{Ctrl}c")

(2)等待控件出现(避免定位失败)

用 WaitForExist() 等待控件加载,超时抛出异常(比 time.sleep() 更灵活):

# 等待按钮出现,超时 5 秒(True 表示找到返回控件,False 表示超时)
button = 父控件.ButtonControl(Name="确定").WaitForExist(timeout=5)
if button:
    button.Click()
else:
    print("控件未找到!")

(3)获取控件属性

通过控件对象的属性获取信息(如文本、是否可见):

# 获取按钮文本
print(button.Name)

# 获取输入框内容
print(edit.GetValue())

# 判断控件是否可见
print(control.IsVisible())

# 获取控件位置和大小
print(control.BoundingRectangle)  # 返回 (x1, y1, x2, y2)

 

五、常见问题与解决方案

1. 控件定位失败

原因 1:控件属性错误(如 Name 拼写错误、ClassName 不对)→ 用 Inspect 重新确认属性。

原因 2:控件未加载完成 → 用 WaitForExist(timeout=5) 替代 time.sleep()。

原因 3:应用需要管理员权限 → 以管理员身份运行 Python 脚本。

原因 4:控件在后台窗口 → 先调用 窗口.SetActive() 激活窗口。

2. 输入框无法输入

确保输入框已获取焦点:edit.SetFocus() 后再 SendKeys()。

避免特殊字符转义:路径用原始字符串 r"C:\path",特殊键用 {} 包裹(如 {Enter})。

3. 菜单无法点击

菜单需要先展开父菜单:点击「文件」后,需等待子菜单显示(time.sleep(0.5))再点击子菜单。

六、扩展示例:操控 Chrome 浏览器

目标:打开 Chrome → 访问百度 → 输入关键词 → 点击搜索。

前提条件

Chrome 安装路径默认:C:\Program Files\Google\Chrome\Application\chrome.exe。

用 Inspect 确认 Chrome 控件属性(地址栏 Name="地址和搜索栏",搜索按钮 Name="百度一下")。

代码示例

import uiautomation as auto
import subprocess
import time

# 1. 启动 Chrome 并访问百度
chrome_path = r"C:\Program Files\Google\Chrome\Application\chrome.exe"
subprocess.Popen([chrome_path, "https://www.baidu.com"])
time.sleep(3)  # Chrome 启动较慢,延长等待时间

# 2. 定位 Chrome 窗口(标题包含「百度一下」)
chrome_window = auto.WindowControl(Name_re=".*百度一下.*", ClassName="Chrome_WidgetWin_1")
chrome_window.SetActive()
time.sleep(1)

# 3. 定位地址栏并输入关键词(百度首页地址栏 Name="地址和搜索栏")
address_bar = chrome_window.EditControl(Name="地址和搜索栏")
address_bar.SetFocus()
address_bar.SendKeys("uiautomation 教程{Enter}")  # 输入后回车搜索

# 4. 保持窗口打开 5 秒
time.sleep(5)

七、总结

uiautomation 库的核心是「精准定位控件 + 调用专属操作」,新手入门关键:

熟练使用 Inspect 工具获取控件的 Name、AutomationId、ClassName。

优先用 AutomationId 定位(最稳定),其次是 Name 和 ClassName。

操作前确保控件加载完成(WaitForExist)和窗口激活(SetActive)。

后续可学习:控件遍历(Control.GetChildren())、弹窗处理、异常捕获、复杂应用(如 Excel、Qt 程序)自动化等。如果需要特定应用的详细教程,可以补充说明场景!