Windows 自动化工具 pywinauto 使用指南

Windows 自动化工具 pywinauto 使用指南

pywinauto 使用指南简介pywinauto 是一个用于 Windows 系统下的 GUI 自动化测试和操作的 Python 库。它允许您通过代码自动化控制 Windows 应用程序,执行点击、输入文本、获取界面元素等操作,非常适合 GUI 自动化测试和重复性操作的自动化。

当前版本: 0.6.9

主要功能自动化启动和连接 Windows 应用程序查找和操作窗口及控件模拟用户操作(点击、输入、拖拽等)获取窗口和控件的属性和状态支持多种后端(backend)模式,包括 UIA(UI Automation)和传统的 win32环境准备系统要求Windows 操作系统(Windows 7/8/10/11)Python 3.6 或更高版本仅支持 Windows 平台,不支持 Linux 或 macOS安装依赖# 安装主要库

pip install pywinauto

# 安装其他可能用到的依赖

pip install pillow # 用于图像处理,截图功能需要

pip install opencv-python # 用于图像识别(可选)

pip install python-cv # 用于复杂图像处理(可选)后端选择pywinauto 支持两种后端:

UIA (UI Automation) - 推荐用于 Windows 7 及以上系统,支持更多的控件类型

app = Application(backend="uia")Win32 - 用于较老的应用程序或特殊情况

app = Application(backend="win32")开发工具推荐为了更方便地识别和定位 Windows 应用程序中的控件,推荐使用以下工具:

Inspect.exe - Windows SDK 自带的 UI 检查工具Spy++ - Visual Studio 自带的窗口检查工具UISpy - Windows SDK 工具Accessibility Insights for Windows - 微软开发的辅助工具安装方法pip install pywinauto基本使用导入必要模块from pywinauto.application import Application

from pywinauto.findwindows import find_elements, find_element

import time启动应用程序# 使用 UIA 后端启动应用程序

app = Application(backend="uia").start("应用程序路径")

# 示例:启动记事本

app = Application(backend="uia").start("notepad.exe")连接到已运行的应用程序# 通过窗口标题连接

app = Application(backend="uia").connect(title="窗口标题")

# 通过窗口标题的正则表达式连接

app = Application(backend="uia").connect(title_re="窗口标题.*")

# 通过进程 ID 连接

app = Application(backend="uia").connect(process=1234)窗口和控件操作# 获取顶层窗口

main_window = app.top_window()

# 等待窗口准备就绪

main_window.wait('ready', timeout=10)

# 打印窗口内所有控件的层次结构

print(main_window.dump_tree())

# 通过标题和控件类型查找特定控件

button = main_window.child_window(title="确定", control_type="Button")

# 点击按钮

button.click()

# 向文本框输入内容

edit = main_window.child_window(control_type="Edit")

edit.type_keys("Hello World!")

# 绘制红色边框以突出显示控件(调试时很有用)

button.draw_outline(colour='red', thickness=2)Desktop 对象可以使用 Desktop 对象直接访问桌面上的窗口:

from pywinauto import Desktop

# 获取桌面窗口

desktop = Desktop(backend="uia")

# 获取所有可见窗口

windows = desktop.windows()

# 通过标题访问特定窗口

notepad_window = desktop['记事本']进阶功能详解1. 保存控件菜单树结构 print_control_identifiers()此方法可以打印出窗口中所有控件的标识符和属性,是调试和开发自动化脚本的重要工具:

# 打印窗口所有控件的标识符信息

main_window.print_control_identifiers()

# 也可以针对特定控件打印其子控件的标识符

panel = main_window.child_window(title="面板", control_type="Pane")

panel.print_control_identifiers()输出示例:

Control Identifiers:

Button - '确定' (L1373, T636, R1455, B666)

['确定Button', '确定', 'Button', 'Button0', 'Button1']

Button - '取消' (L1373, T589, R1455, B619)

['取消Button', '取消', 'Button2']2. 设置全局等待时间 Timingspywinauto 查找窗口和控件时会有超时时间与轮询机制,可以通过 timings 模块设置全局等待时间:

from pywinauto import timings

# 设置默认超时时间(秒)

timings.Timings.window_find_timeout = 5.0 # 查找窗口超时

timings.Timings.app_start_timeout = 20.0 # 启动应用程序超时

timings.Timings.app_connect_timeout = 5.0 # 连接应用程序超时

timings.Timings.after_click_wait = 0.5 # 点击后等待时间

# 恢复默认时间设置

timings.Timings.defaults()timings 模块提供了三种预设模式:

# 快速模式 - 减少各种操作的等待时间

timings.Timings.fast()

# 默认模式 - 使用默认等待时间设置

timings.Timings.defaults()

# 慢速模式 - 增加各种操作的等待时间,适用于较慢的应用程序

timings.Timings.slow()以下是可以调整的各个时序设置:

window_find_timeout (default 5) # 查找窗口的超时时间

window_find_retry (default .09) # 查找窗口的重试间隔

app_start_timeout (default 10) # 启动应用程序的超时时间

app_start_retry (default .90) # 启动应用程序的重试间隔

app_connect_timeout (default 5.) # 连接应用程序的超时时间

app_connect_retry (default .1) # 连接应用程序的重试间隔

cpu_usage_interval (default .5) # CPU使用率检查间隔

cpu_usage_wait_timeout (default 20) # 等待CPU使用率降低的超时时间

exists_timeout (default .5) # 检查元素存在的超时时间

exists_retry (default .3) # 检查元素存在的重试间隔

after_click_wait (default .09) # 点击后等待时间

after_clickinput_wait (default .09) # 使用点击输入后等待时间

after_menu_wait (default .1) # 菜单操作后等待时间

after_sendkeys_key_wait (default .01) # 发送按键后每个键的等待时间

after_button_click_wait (default 0) # 按钮点击后等待时间

before_closeclick_wait (default .1) # 关闭点击前等待时间

closeclick_retry (default .05) # 关闭点击重试间隔

closeclick_dialog_close_wait (default 2) # 关闭对话框后等待时间

after_closeclick_wait (default .2) # 关闭点击后等待时间

after_windowclose_timeout (default 2) # 窗口关闭后超时时间

after_windowclose_retry (default .5) # 窗口关闭后重试间隔

after_setfocus_wait (default .06) # 设置焦点后等待时间

setfocus_timeout (default 2) # 设置焦点的超时时间

setfocus_retry (default .1) # 设置焦点的重试间隔

after_setcursorpos_wait (default .01) # 设置光标位置后等待时间

sendmessagetimeout_timeout (default .01) # 发送消息超时时间

after_tabselect_wait (default .05) # 选项卡选择后等待时间

after_listviewselect_wait (default .01) # 列表视图选择后等待时间

after_listviewcheck_wait (default .001) # 列表视图勾选后等待时间

listviewitemcontrol_timeout (default 1.5) # 列表视图项控制的超时时间

after_treeviewselect_wait (default .1) # 树视图选择后等待时间

after_toobarpressbutton_wait (default .01) # 工具栏按钮按下后等待时间

after_updownchange_wait (default .1) # 上下更改后等待时间

after_movewindow_wait (default 0) # 移动窗口后等待时间

after_buttoncheck_wait (default 0) # 按钮勾选后等待时间

after_comboboxselect_wait (default .001) # 组合框选择后等待时间

after_listboxselect_wait (default 0) # 列表框选择后等待时间

after_listboxfocuschange_wait (default 0) # 列表框焦点更改后等待时间

after_editsetedittext_wait (default 0) # 编辑框设置文本后等待时间

after_editselect_wait (default .02) # 编辑框选择后等待时间

drag_n_drop_move_mouse_wait (default .1) # 拖放移动鼠标等待时间

before_drag_wait (default .2) # 拖动前等待时间

before_drop_wait (default .1) # 放下前等待时间

after_drag_n_drop_wait (default .1) # 拖放后等待时间

scroll_step_wait (default .1) # 滚动步骤等待时间适当调整这些时间设置可以提高自动化脚本的稳定性和成功率。对于较慢的应用程序,增加等待时间;对于响应迅速的应用程序,可以减少等待时间以提高效率。

3. 鼠标操作与滚动列表鼠标操作包括点击、右键、双击、拖拽等:

# 直接使用鼠标模块进行操作

from pywinauto import mouse

# 单击鼠标左键(指定坐标位置)

mouse.click(coords=(100, 100))

# 鼠标右击

mouse.right_click(coords=(100, 200))

# 鼠标双击

mouse.double_click(coords=(100, 200))

# 鼠标长按、拖动、释放(拖拽操作)

mouse.press(coords=(200, 400))

mouse.move(coords=(100, 0)) # 相对移动

mouse.release(coords=(300, 400))

# 鼠标滚轮操作

mouse.scroll(coords=(0, 0), wheel_dist=1) # 正数向上滚动,负数向下滚动

# 鼠标中键单击

mouse.wheel_click(coords=(0, 0))

# 控件级别的鼠标操作

button.click() # 左键点击控件

button.click_input() # 模拟真实鼠标点击(移动鼠标到位置再点击)

button.right_click() # 右键点击控件

button.right_click_input() # 模拟真实鼠标右键点击

button.double_click() # 双击控件

button.double_click_input() # 模拟真实鼠标双击滚动列表控件滚动列表的方法有两种:

# 方法1:使用控件的滚动方法(某些控件支持)

list_control = main_window.child_window(control_type="List")

list_control.scroll("down", "page", count=2) # 向下滚动2页

list_control.scroll("up", "line", count=5) # 向上滚动5行

# 方法2:使用鼠标滚轮滚动(更通用)

# 首先获取控件的矩形区域

list_rect = list_control.rectangle()

# 然后在该区域内使用鼠标滚轮

mouse.scroll(coords=(list_rect.left + 20, list_rect.top + 30), wheel_dist=-2) # 向下滚动,负数表示向下

# 实际应用示例:滚动微信聊天记录

app = Application(backend='uia').connect(path=r'C:\Program Files (x86)\Tencent\WeChat\WeChat.exe')

win = app.window(title="微信", class_name='WeChatMainWndForPC')

chat_list = win.child_window(title="会话", control_type="List").rectangle()

mouse.scroll(coords=(chat_list.left + 20, chat_list.top + 30), wheel_dist=-2) # 向下滚动注意:wheel_dist参数的值为正表示向上滚动,为负表示向下滚动,数值大小决定滚动的距离。

4. 查找多个相同控件使用 found_index当同一个窗口中有多个相同属性的控件时,直接使用child_window()可能会引发ElementAmbiguousError错误。这时可以使用found_index参数来指定第几个匹配的控件:

# 获取第一个匹配的按钮

first_button = main_window.child_window(title="下一步", control_type="Button", found_index=0)

# 获取第二个匹配的按钮

second_button = main_window.child_window(title="下一步", control_type="Button", found_index=1)

# 获取所有匹配的按钮

all_buttons = main_window.children(title="下一步", control_type="Button")实际应用示例 - 处理记事本中的多个菜单栏:

from pywinauto import Application

# 启动记事本

app = Application('uia').start("notepad.exe")

win = app.window(title_re="无标题 - 记事本")

# 输入内容

win.child_window(title="文本编辑器").set_text("hello world")

# 查找MenuBar - 如果直接查找会报错

# menu = win.child_window(control_type="MenuBar") # 这会引发错误

# 查找第一个MenuBar

menu0 = win.child_window(control_type="MenuBar", found_index=0)

print(menu0.window_text())

# 查找第二个MenuBar

menu1 = win.child_window(control_type="MenuBar", found_index=1)

print(menu1.window_text())错误示例:当有多个匹配元素但没有使用found_index时,会引发以下错误:

pywinauto.findwindows.ElementAmbiguousError: There are 2 elements that match the criteria

{'control_type': 'MenuBar', 'top_level_only': False, 'parent': , 'backend': 'uia'}注意:found_index参数的索引从 0 开始,即 0 表示第一个匹配的控件,1 表示第二个,以此类推。

5. 等待方法 wait() 和 wait_not()详细的等待方法使用:

# 等待窗口处于特定状态

window.wait('ready') # 等待窗口准备就绪

window.wait('exists') # 等待窗口存在

window.wait('visible') # 等待窗口可见

window.wait('enabled') # 等待窗口启用

# 等待窗口不处于特定状态

window.wait_not('visible') # 等待窗口不可见

window.wait_not('exists') # 等待窗口不存在

# 使用超时参数

window.wait('ready', timeout=30) # 最多等待30秒

window.wait_not('exists', timeout=10) # 最多等待10秒6. 组合框控件 ComboBox 操作组合框控件(ComboBox)是 Windows 应用程序中常见的下拉选择控件。pywinauto 提供了两种操作组合框的方法:

# 方法1: 使用select方法直接选择选项

# 获取ComboBox控件

combo_box = main_window.child_window(control_type="ComboBox")

# 展开下拉列表

combo_box.expand()

# 选择特定选项(直接选择,但屏幕可能会闪烁)

combo_box.select("选项文本")

# 获取所有选项

options = combo_box.item_texts()

# 通过索引选择

combo_box.select(2) # 选择第三个选项(索引从0开始)

# 方法2: 更接近真实操作的方法(推荐)

# 1.先点开选项

combo_box.click_input()

# 2.选择内容

main_window.child_window(title="选项文本", control_type="ListItem").click_input()实际应用示例 - 操作记事本的编码选择:

from pywinauto import Application

# 启动记事本

app = Application('uia').start("notepad.exe")

win = app.window(title_re="无标题 - 记事本")

# 输入内容

win.child_window(title="文本编辑器").set_text("hello world")

# 文件-另存为

win.menu_select('文件(F) -> 另存为(A)...')

# 操作弹出文件选择框

save_win = win.child_window(title="另存为", control_type="Window")

# 方法1: 使用select方法(可能导致屏幕闪烁)

save_win.child_window(title="编码(E):", control_type="ComboBox").select("UTF-8")

# 方法2: 更接近真实操作的方法(推荐)

# 1.先点开选项

save_win.child_window(title="编码(E):", control_type="ComboBox").click_input()

# 2.选择内容

save_win.child_window(title="UTF-8", control_type="ListItem").click_input()注意:select()方法虽然简便,但可能会导致屏幕闪烁;而使用click_input()方法分两步操作更接近真实手工操作,通常是更稳定的选择。

7. 窗口和控件截图 capture_as_image()pywinauto 提供了对窗口和控件进行截图的功能,这在调试和报告生成中非常有用:

# 安装必要的依赖

# pip install Pillow # PIL库是必需的,用于图像处理

from pywinauto import Application

# 启动记事本

app = Application('uia').start("notepad.exe")

win = app.window(title_re="无标题 - 记事本")

# 对整个窗口截图

window_image = win.capture_as_image()

window_image.save("window_screenshot.png")

# 对特定控件截图

menu = win.child_window(title="应用程序", auto_id="MenuBar", control_type="MenuBar")

menu_image = menu.capture_as_image()

menu_image.save("menu_screenshot.png")

# 对按钮控件截图

button_image = button.capture_as_image()

button_image.save("button_screenshot.png")

# 截取特定区域(需要使用PIL库的ImageGrab)

from PIL import ImageGrab

region_image = ImageGrab.grab(bbox=(100, 100, 300, 300)) # (left, top, right, bottom)

region_image.save("region_screenshot.png")注意事项:

使用capture_as_image()功能需要安装 PIL 库 (pip install Pillow)窗口截图可能会包含其他窗口的背景,特别是当窗口有透明部分时控件截图更加精确,只截取控件本身的区域可以使用 PIL 库的其他功能对截图进行处理,如裁剪、缩放、添加文字等8. 键盘快捷键操作 send_keys()pywinauto 提供了强大的键盘模拟功能,可以发送各种键盘按键和组合键:

from pywinauto.keyboard import send_keys

# 基本按键

send_keys("Hello World") # 输入文本

send_keys("{ENTER}") # 回车键

send_keys("{TAB}") # Tab键

send_keys("{F1}") # F1键

# 组合键

send_keys("^a") # Ctrl+A(全选)

send_keys("^c") # Ctrl+C(复制)

send_keys("^v") # Ctrl+V(粘贴)

send_keys("+{END}") # Shift+End(选择到行尾)

send_keys("%{F4}") # Alt+F4(关闭窗口)

# 特殊按键

send_keys("{VK_SPACE}") # 空格键

send_keys("{BACKSPACE}") # 退格键

send_keys("{DELETE}") # 删除键

send_keys("{PAUSE}") # 暂停键

# 直接向控件发送按键

edit_box.type_keys("文本内容{ENTER}")控件文本输入的两种方法对比:

set_text方法:

直接设置控件的文本值光标位置在最左边按 enter 后,文本被换行不支持快捷键操作示例:edit_box.set_text("hello world")type_keys方法:

模拟真实的键盘输入支持中文输入光标位置在最右边支持各种快捷键操作示例:edit_box.type_keys("hello world^s") # 输入文本并保存(Ctrl+S)示例 - 在记事本中使用快捷键:

from pywinauto import Application

from pywinauto.keyboard import send_keys

import time

# 启动记事本

app = Application('uia').start("notepad.exe")

win = app.window(title_re="无标题 - 记事本")

# 使用type_keys输入文本

win.type_keys("Hello World!^a") # 输入文本并全选(Ctrl+A)

time.sleep(1)

# 复制文本

send_keys("^c")

time.sleep(1)

# 粘贴文本

send_keys("^v^v") # 粘贴两次

time.sleep(1)

# 使用Alt+F4关闭记事本

send_keys("%{F4}")推荐:对于文本输入,通常建议使用type_keys()方法,因为它更接近真实用户操作,支持更多功能,并且在大多数情况下更可靠。

9. 操作 MenuItem 菜单项pywinauto 提供了多种操作应用程序菜单的方法:

# 方法1: 使用menu_select方法(最简便的方法)

# 通过路径操作菜单项

main_window.menu_select("文件->打开") # 点击"文件"菜单下的"打开"子菜单

# 对于包含快捷键标记的菜单项

main_window.menu_select("文件(F)->打开(O)") # 带有快捷键标记的菜单项

main_window.menu_select('文件(&F)->打开(&O)') # 另一种快捷键标记形式

# 方法2: 获取菜单对象,然后操作

# 获取菜单对象

menu = main_window.menu()

# 获取主菜单项并点击

file_menu = menu.item_by_path("文件")

file_menu.click()

# 获取子菜单项并点击

open_menu = menu.item_by_path("文件->打开")

open_menu.click()

# 方法3: 使用快捷键访问菜单

from pywinauto.keyboard import send_keys

send_keys("%f") # Alt+F 打开"文件"菜单

send_keys("o") # 选择"打开"子菜单实际应用示例 - 操作记事本的菜单:

from pywinauto import Application

import time

# 启动记事本

app = Application('uia').start("notepad.exe")

win = app.window(title_re="无标题 - 记事本")

win.wait('ready')

# 方法1: 使用menu_select操作"文件"菜单中的"页面设置"

win.menu_select("文件(F)->页面设置(U)...")

time.sleep(1)

# 关闭页面设置对话框

page_setup = app.window(title="页面设置")

page_setup.child_window(title="确定", control_type="Button").click()

# 方法2: 使用menu对象操作"编辑"菜单

menu = win.menu()

edit_menu = menu.item_by_path("编辑(E)")

edit_menu.click()

time.sleep(0.5)

# 点击"编辑"菜单下的"时间/日期"

date_menu = menu.item_by_path("编辑(E)->时间/日期(D)")

date_menu.click()

# 方法3: 使用快捷键

send_keys("^a") # Ctrl+A 全选

send_keys("^x") # Ctrl+X 剪切注意事项:

在使用menu_select()时,菜单路径使用"->"分隔如果菜单项有特殊字符,如"查找和替换",也可以直接包含在路径中对于一些应用程序,菜单项可能包含访问键标记(如"文件(&F)"),需要正确包含这些标记如果菜单项没有文本或文本识别有问题,可以使用索引方式,如"#0->#1"表示第一个主菜单的第二个子菜单10. 获取控件属性和文本内容# 获取控件文本

text = edit_box.texts() # 返回文本列表

text_str = edit_box.window_text() # 返回文本字符串

# 获取控件属性

enabled = button.is_enabled() # 控件是否启用

visible = button.is_visible() # 控件是否可见

rect = button.rectangle() # 控件矩形区域

# 获取特定属性

control_type = button.element_info.control_type

automation_id = button.element_info.automation_id

class_name = button.element_info.class_name

# 获取复选框或单选按钮状态

checked = checkbox.is_checked() # 复选框是否勾选11. 操作弹出文件选择框# 点击"打开文件"按钮

open_button.click()

# 等待文件选择对话框出现

file_dialog = app.window(title="打开")

file_dialog.wait('ready', timeout=10)

# 输入文件路径

file_path_edit = file_dialog.child_window(control_type="Edit")

file_path_edit.set_text("C:\\path\\to\\file.txt")

# 或者直接输入文件名

file_name_edit = file_dialog.child_window(control_type="Edit", found_index=0)

file_name_edit.set_text("file.txt")

# 点击"打开"按钮确认

open_dialog_button = file_dialog.child_window(title="打开", control_type="Button")

open_dialog_button.click()12. 操作弹出新窗口上按钮# 点击会弹出新窗口的按钮

button_popup = main_window.child_window(title="设置", control_type="Button")

button_popup.click()

# 等待新窗口出现

popup_window = app.window(title="设置对话框")

popup_window.wait('ready', timeout=10)

# 操作新窗口上的控件

ok_button = popup_window.child_window(title="确定", control_type="Button")

ok_button.click()

# 等待新窗口关闭

popup_window.wait_not('exists', timeout=5)13. 操作级联菜单 menu_select()# 复杂的多级菜单操作

main_window.menu_select("文件->导出->PDF文件")

# 如果菜单项有特殊字符或空格,使用引号

main_window.menu_select("编辑->查找和替换->高级替换")

# 使用索引操作菜单(如菜单项没有文本)

main_window.menu_select("#0->#1->#0") # 第一个主菜单->第二个子菜单->第一个子子菜单14. 操作窗口控件 child_window()更多控件查找和操作方法:

# 使用多种属性组合查找控件

button = main_window.child_window(title="保存", control_type="Button", auto_id="saveButton")

# 使用部分标题匹配

button = main_window.child_window(title_re="保存.*", control_type="Button")

# 获取所有特定类型的控件

all_buttons = main_window.children(control_type="Button")

all_edit_boxes = main_window.children(control_type="Edit")

# 获取直接子控件vs所有后代控件

direct_children = main_window.children()

all_descendants = main_window.descendants()

# 使用相对位置查找

above_control = main_window.child_window(control_type="Button", top_level_only=True)

below_control = above_control.get_next()

previous_control = below_control.get_previous()15. 操作指定 window 窗口# 通过标题获取窗口对象

notepad_window = app.window(title="无标题 - 记事本")

# 通过类名获取窗口

dialog = app.window(class_name="#32770")

# 通过自动化ID获取窗口

main_window = app.window(auto_id="mainWindow")

# 窗口操作

notepad_window.minimize() # 最小化窗口

notepad_window.maximize() # 最大化窗口

notepad_window.restore() # 还原窗口

notepad_window.close() # 关闭窗口

# 窗口状态检查

is_minimized = notepad_window.is_minimized()

is_maximized = notepad_window.is_maximized()

is_normal = notepad_window.is_normal()16. 启动指定应用程序# 简单启动(使用系统默认路径)

app = Application(backend="uia").start("notepad.exe")

# 指定完整路径启动

app = Application(backend="uia").start(r"C:\Windows\System32\notepad.exe")

# 启动并带参数

app = Application(backend="uia").start(r"notepad.exe C:\temp\test.txt")

# 启动并等待初始化完成

app = Application(backend="uia").start("explorer.exe")

app.wait_cpu_usage_lower(threshold=5, timeout=30) # 等待CPU使用率低于5%

# 以管理员权限启动

app = Application(backend="uia").start("cmd.exe", wait_for_idle=False)错误处理与调试1. 异常处理使用 try-except 捕获常见异常:

from pywinauto.findwindows import ElementNotFoundError, ElementAmbiguousError

try:

button = main_window.child_window(title="确定", control_type="Button")

button.click()

except ElementNotFoundError:

print("未找到指定按钮")

# 进行替代操作

except ElementAmbiguousError:

print("找到多个匹配的按钮,请使用更精确的条件")

# 尝试使用更多条件进行查找2. 调试技巧调试自动化脚本时的有用方法:

# 1. 打印应用程序中所有顶层窗口

print(app.windows())

# 2. 打印当前窗口所有控件

main_window.print_control_identifiers(depth=None) # 打印所有层级

main_window.print_control_identifiers(depth=3) # 只打印3层深度

# 3. 将控件结构保存到文件

with open('controls.txt', 'w', encoding='utf-8') as f:

f.write(main_window.print_control_identifiers(depth=None, filename=None))

# 4. 高亮显示找到的控件

button.draw_outline(colour='red', thickness=2)

# 5. 在弹出对话框前暂停脚本执行

input("按Enter键继续...")3. 性能优化提高自动化脚本性能的方法:

# 1. 减少不必要的查找操作

button = main_window.child_window(title="确定", control_type="Button")

button.click()

button.wait_not('visible') # 使用同一个button对象

# 2. 缓存窗口对象

notepad_window = app.window(title="无标题 - 记事本")

# 在多次操作同一窗口时重用此对象

# 3. 使用更精确的查找条件

button = main_window.child_window(title="确定", control_type="Button", auto_id="OKButton")

# 添加auto_id等属性可以加快查找速度

# 4. 设置适当的超时时间

from pywinauto import timings

timings.Timings.window_find_timeout = 2.0 # 默认为5秒,可根据需要调整实际应用场景1. 文本编辑器自动化# 自动化操作记事本

app = Application(backend="uia").start("notepad.exe")

notepad = app.window(title_re=".*记事本")

notepad.wait('ready')

# 输入文本

notepad.type_keys("这是一段自动输入的文本", with_spaces=True)

# 保存文件

notepad.menu_select("文件->保存")

save_dialog = app.window(title="另存为")

save_dialog.wait('ready')

file_name_edit = save_dialog.child_window(control_type="Edit")

file_name_edit.set_text("test.txt")

save_button = save_dialog.child_window(title="保存", control_type="Button")

save_button.click()2. 表单填写自动化# 连接到已打开的应用程序

app = Application(backend="uia").connect(title_re="注册表单.*")

form_window = app.window(title_re="注册表单.*")

# 填写表单字段

name_edit = form_window.child_window(title="姓名:", control_type="Edit", found_index=1)

name_edit.set_text("张三")

email_edit = form_window.child_window(title="电子邮件:", control_type="Edit", found_index=1)

email_edit.set_text("zhangsan@example.com")

# 选择下拉框选项

province_combo = form_window.child_window(title="省份:", control_type="ComboBox")

province_combo.select("北京")

# 选择单选按钮

gender_male = form_window.child_window(title="男", control_type="RadioButton")

gender_male.click()

# 勾选复选框

agreement_check = form_window.child_window(title="我同意服务条款", control_type="CheckBox")

if not agreement_check.is_checked():

agreement_check.click()

# 提交表单

submit_button = form_window.child_window(title="提交", control_type="Button")

submit_button.click()3. 处理系统对话框# 处理文件复制确认对话框

confirm_dialog = app.window(title="确认文件替换")

if confirm_dialog.exists():

yes_button = confirm_dialog.child_window(title="是", control_type="Button")

yes_button.click()

# 处理警告对话框

warning_dialog = app.window(title="警告")

if warning_dialog.exists():

ok_button = warning_dialog.child_window(title="确定", control_type="Button")

ok_button.click()

# 处理UAC提升权限对话框

uac_dialog = Desktop(backend="uia").window(title="用户帐户控制")

if uac_dialog.exists():

yes_button = uac_dialog.child_window(title="是", control_type="Button")

yes_button.click()4. 复杂控件处理# 处理日期选择器

date_picker = window.child_window(control_type="DateTimePicker")

date_picker.click_input() # 打开日期选择器

# 选择月份

month_combo = date_picker.child_window(control_type="ComboBox", found_index=0)

month_combo.select("12月")

# 选择日期

day_button = date_picker.child_window(title="25", control_type="Button")

day_button.click()

# 处理树形控件

tree_view = window.child_window(control_type="Tree")

tree_item = tree_view.get_item(['父节点', '子节点', '叶子节点'])

tree_item.click()

# 处理列表视图

list_view = window.child_window(control_type="List")

list_items = list_view.items()

for item in list_items:

print(item.texts())常见问题与解决方案找不到窗口或控件:

问题:ElementNotFoundError 错误解决方案:

使用 print(window.dump_tree()) 或 print_control_identifiers() 查看控件层次结构检查控件的标识符是否正确(标题、ID、类名等)增加等待时间,某些控件可能需要时间加载尝试使用不同的属性组合来定位控件操作过快导致失败:

问题:自动化操作太快,应用程序反应不过来解决方案:

在关键操作之间添加 time.sleep() 适当延时增加全局等待时间 timings.Timings.slow()使用 wait() 和 wait_not() 等待控件状态变化匹配到多个控件:

问题:ElementAmbiguousError 错误解决方案:

使用 found_index 参数指定具体的控件添加更多的属性条件缩小匹配范围使用 children() 获取所有匹配控件,然后遍历处理后端选择问题:

问题:某些应用程序用一种后端无法正常工作解决方案:

现代应用通常使用 "uia" 后端:Application(backend="uia")旧应用程序可能需要 "win32" 后端:Application(backend="win32")尝试两种后端,看哪种更适合你的应用控件识别不稳定:

问题:同一个控件有时能找到,有时找不到解决方案:

使用多个属性结合定位控件,如 title、class_name、control_type 结合使用 title_re 进行模糊匹配:child_window(title_re=".*保存.*")先定位父控件,再从父控件中查找子控件权限不足:

问题:无法操作需要管理员权限的应用解决方案:

以管理员身份运行 Python 脚本处理 UAC 对话框:Desktop().window(title="用户帐户控制").child_window(title="是").click()文本输入问题:

问题:type_keys() 或 set_text() 无法正确输入文本解决方案:

对于复杂输入,优先使用 type_keys()对于中文等非 ASCII 字符,确保正确的编码尝试先清空文本框:edit_box.set_text("") 然后再输入菜单操作失败:

问题:menu_select() 无法找到或点击菜单项解决方案:

确认菜单路径是否正确,包括访问键标记如 "(F)"尝试使用快捷键操作菜单使用菜单对象直接操作:menu.item_by_path("文件").click()动态变化的 UI:

问题:UI 元素位置或属性动态变化解决方案:

使用更稳定的属性(如automation_id)而非位置来定位实现异常处理和重试机制使用条件检查确认 UI 状态后再操作性能问题:

问题:自动化脚本运行缓慢解决方案:

缓存常用窗口和控件对象,避免重复查找使用更精确的查找条件加快查找速度调整 timings 设置,减少不必要的等待时间对于大型应用程序,使用 wait_cpu_usage_lower() 等待 CPU 使用率降低截图失败:

问题:capture_as_image() 返回 None 或截图不完整解决方案:

确保已安装 PIL 库:pip install Pillow确保窗口在前台且可见对于部分最小化的窗口,先恢复窗口状态ComboBox 操作问题:

问题:下拉框选择项目失败解决方案:

使用两步操作:先 click_input() 展开,再选择项目检查 ComboBox 类型,不同类型的 ComboBox 可能需要不同操作方式实用技巧使用 spy++ 或 Windows 自带的 "Inspect" 工具帮助识别窗口和控件属性使用 print(control.print_control_identifiers()) 打印控件的所有可能标识符对于复杂的窗口结构,使用 dump_tree() 方法查看完整的控件层次对于调试,使用 draw_outline() 方法高亮显示找到的控件捕获异常以处理可能出现的窗口或控件未找到情况对于性能敏感的应用,尝试使用 app.wait_cpu_usage_lower() 等待 CPU 使用率降低示例代码from pywinauto.application import Application

import time

# 启动计算器

app = Application(backend="uia").start("calc.exe")

time.sleep(1)

# 获取主窗口

calc = app.window(title="计算器")

# 点击数字和运算符

calc.child_window(title="1", control_type="Button").click()

calc.child_window(title="加", control_type="Button").click()

calc.child_window(title="2", control_type="Button").click()

calc.child_window(title="等于", control_type="Button").click()

# 获取结果

result = calc.child_window(auto_id="CalculatorResults").texts()[0]

print(f"计算结果: {result}")参考资源pywinauto 官方文档pywinauto GitHub 仓库上海-悠悠的博客教程Windows UI 自动化官方文档《Python GUI 自动化测试》推荐书籍

相关推荐

怎样查看钽电容的耐压值 钽电容的选型设计有哪些要求呢?
世界杯F组最新积分排名 加拿大提前一轮小组出局
105电容等于几UF怎么换算
365bet网站是多少

105电容等于几UF怎么换算

📅 06-30 👁️ 281