一、等待
案例:没有添加等待导致引发的错误
from pywinauto import Application
app = Application(backend='uia').connect(process=24600)
win = app.window(title_re='.*Sublime Text.*')
#添加等待
#win.wait('exists')
#最⼩化
win.minimize()
print("is_minimized:",win.is_minimized())
win.maximize()
print("is_maximized:",win.is_maximized())
win.close()
把等待代码注视掉,程序运⾏报错:

GUI应⽤程序⾏为通常不稳定,脚本需要等待,直到出现新窗⼝或关闭/隐藏现有窗⼝。pywinauto可以隐式地(默认超时)灵活地等待对话框初始化,或者明确地使⽤专⽤⽅法/函数来帮助您使代码更容易和更可靠。
1.1 wait/wait_not()
- wait(self, wait_for, timeout=None, retry_interval=None)
- wait_not(self, wait_for_not, timeout=None, retry_interval=None)
参数说明:
wait_for :表⽰选择的窗⼝状态
- exists :表⽰窗⼝是⼀个有效的句柄
- visible :表⽰窗⼝不隐藏,可以看到
- enable :表⽰窗⼝未被禁⽤,可操作
- ready :表⽰窗⼝可⻅且已启⽤
- active :表⽰窗⼝处于活动状态
timeout :表⽰超时
retry_interval :表⽰重试时间间隔,单位为秒s
wait_not 与 wait() 类似, wait 是等待处于某种状态,⽽ wait_not 是等待不处于某种状 态,这⾥以wait为例说明
使⽤⽰例:"exists" 和 "visible"
from pywinauto.application import Application
app = Application(backend='uia').connect(process=38544)
win = app.window(title_re='.*Sublime Text.*')
#检查窗⼝是有效的句柄
win.wait('exists')
#检查窗⼝是否可⻅
win.wait('visible')
#检查窗⼝是否未被禁⽤
win.wait('enabled')
#检查窗⼝是否准备就绪
win.wait('ready')
窗⼝被最⼩化之后,在桌⾯就不可⻅了,因此最⼩化时需要将等待状态改为 "exists" ,应⽤程序界 ⾯在桌⾯可⻅时等待状态可以设置为 "visible"
"enabled"

#打开计算器
# app = Application(backend="uia").start("calc.exe")
app = Application(backend="uia").connect(process=17892)
win = app.window(title="计算器")
win.wait("visible")
#启⽤的按钮
enable_btn = win.child_window(title="记忆减法", auto_id="MemMinus",
control_type="Button")
#未启⽤的按钮
disabled_btn = win.child_window(title="清除所有记忆",
auto_id="ClearMemoryButton", control_type="Button")
enable_btn.wait("enabled") #---代码执⾏通过
disabled_btn.wait_not("enabled")#---代码执⾏通过
若按钮置灰状态,说明按钮为 disabled 状态,当输⼊项不为空时,按钮⾼亮,此时为 enabled 状态
'ready'

from pywinauto import Application
app = Application(backend="uia").connect(process=17892)
win = app.window(title="计算器")
win.wait("exists")
proc = win.child_window(title="打开导航", auto_id="TogglePaneButton",
control_type="Button")
proc.wait("ready")#等待成功
proc_chid = win.child_window(auto_id="PaneTitleTextBlock", control_type="Text")
proc_chid.wait("ready")#等待失败
is_visible() ⽤于检查元素是否可⻅,除此之外, is_enabled() ⽤于检查元素是否启⽤
'active'
需要注意, 'active' 状态指的是窗⼝是否处于活动状态,需要先操作应⽤程序使得焦点设置在该窗 ⼝上或者配合 set_focus 来使⽤:
from pywinauto import Application
sublime_app = Application(backend="uia").connect(process=9388)
sublime_win = sublime_app.window(title_re=".*Sublime Text.*")
app = Application(backend="uia").connect(process=17892)
win = app.window(title="计算器")
win.set_focus()
win.child_window(title="⼀", auto_id="num1Button",
control_type="Button").click_input()
win.wait("active") #等待成功
sublime_win.wait("active") #等待失败
1.2 wait_until
等待满⾜某个条件 wait_until(timeout, retry_interval,func,value=True,op=operator.eq,*args, **kwargs)
部分参数说明:
- Timeout :超时时间
- retry_interval :重试时间
- func :执⾏的函数
- value :⽐较的值
示例1:
i=0
def work():
global i
i += 1
print("当前i的值为",i)
return i
#等待work返回的结果为5,继续往下执⾏
wait_until(10,1,work,5)
print("等待通过")

⽰例2:
def get_window():
app = Application(backend='uia').connect(process=38544)
win = app.window(title_re='.*Sublime Text.*')
return win.is_visible()
def test_wait():
#等待get_window⽅法返回结果为True
wait_until(10,2,get_window,True)
print("等待通过")
test_wait()
pywinauto 提供了丰富的等待机制,可解决自动化过程中控件状态变化、窗口加载等问题,确保脚本能精准识别目标控件 / 窗口并在合适时机执行操作。本文聚焦实际应用中最常用的几种等待方法,帮助快速掌握核心技巧,保障自动化流程稳定可靠。pywinauto等待
二、控件的操作
2.1点击
1.click_input()
from pywinauto import Application
app = Application(backend='uia').connect(process=8732)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
#点击最⼤化按钮
win.child_window(title="最⼤化", control_type="Button").click_input()
2.right_click_input()
模拟⿏标右键单击操作
from pywinauto import Application
app = Application(backend='uia').connect(process=8732)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
#右键窗⼝
win.right_click_input()
3.double_click_input()
模拟⿏标右键双击操作
from pywinauto import Application
app = Application(backend='uia').connect(process=8732)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
menu = win['应⽤程序']
#双击菜单栏------达到窗⼝最⼤化⽬的
menu.double_click_input()
2.2⽂本
1.texts()
⽤于获取窗⼝或控件中的所有⽂本内容,返回⼀个列表,其中每个元素是⼀个字符串,表⽰窗⼝或控 件中的某个⽂本⽚段
示例1:获取窗⼝的标题
# app = Application(backend='uia').start("D:\software\Sublime Text
3\sublime_text.exe")
app = Application(backend='uia').connect(process=2392)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
print(win.texts())

⽰例2:获取控件的标题
# app = Application(backend='uia').start("D:\software\Sublime Text
3\sublime_text.exe")
app = Application(backend='uia').connect(process=2392)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
file = win.child_window(title="File", control_type="MenuItem")
print(file.texts())

2.window_text()
⽤于获取窗⼝或控件的主⽂本内容,通常是指窗⼝的标题或主要显⽰的⽂本。它返回⼀个字符串。 示例1:
# app = Application(backend='uia').start("D:\software\Sublime Text
3\sublime_text.exe")
app = Application(backend='uia').connect(process=2392)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
print(win.window_text())

示例2:获取控件的标题
# app = Application(backend='uia').start("D:\software\Sublime Text
3\sublime_text.exe")
app = Application(backend='uia').connect(process=2392)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
file = win.child_window(title="File", control_type="MenuItem")
print(file.window_text())

三、⿏标操作
使用 pywinauto 做自动化测试时,常通过控件点击方法实现交互,这类方法支持直接点击控件,也可通过coords参数指定坐标点击。比如用win.double_click_input(coords=(1043, 130))点击 Sublime Text 窗口最大化按钮,语法虽无错误,但这种坐标点击方式在需要更高精度、更灵活的鼠标交互场景中,可能无法满足需求。
from pywinauto import Application
app = Application(backend='uia').connect(process=32936)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
#操作Sublime Text 窗⼝的最⼤化按钮--获取按钮的坐标
win.double_click_input(coords=(1043,130))
为了解决这⼀问题,pywinauto提供了⼀个独⽴的mouse 模块,专⻔⽤于模拟真实⽤⼾的⿏标事 件。这个模块的优势在于,它完全独⽴于控件操作,能够更贴近真实用户的⾏为模式。通过mouse 模块,我们可以直接在屏幕上指定坐标进⾏点击、双击、拖动等操作,⽽⽆需依赖控件的层次结构。
示例: click() ⽅法操作SublimeText窗⼝的最⼤化按钮
from pywinauto import Application
app = Application(backend='uia').connect(process=32936)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
#通过⿏标点击
mouse.click(coords=(1043,130))
⽰例:拖动滚动条
rectangle() :获取元素对应坐标,返回矩形尺⼨,具有top,left,right,bottom属性

mid_point() :获取元素中间位置坐标,返回类型为元组,元组中两个整数分别是X、Y轴的值
from pywinauto import Application
# app = Application(backend='uia').start("mspaint.exe")
app = Application(backend='uia').connect(process=28372)
win = app.window(title="⽆标题 - 画图")
win.wait('visible')
#定位滚动条
right_ScrollBar = win.child_window(title="垂直滚动条",
auto_id="NonClientVerticalScrollBar", control_type="ScrollBar")
right_ScrollBar.wait('visible')
#获取滚动条中间位置
mid = right_ScrollBar.rectangle().mid_point()
#从中间位置下拉
mouse.scroll(coords=(mid.x,mid.y),wheel_dist=500)
mouse 模块常⻅操作:


⾃动化测试场景示例:抖⾳点赞
# app = Application(backend="uia").start("C:\Program Files
(x86)\ByteDance\douyin\douyin.exe")
app = Application(backend="uia").connect(process=14488)
win = app['抖⾳']
win.wait("visible")
#双击点赞
for i in range(0,3):
mid = win.rectangle().mid_point()
mouse.double_click(coords=(mid.x,mid.y))
time.sleep(1)
#滑到下⼀个视频
mouse.scroll(coords=(mid.x, mid.y), wheel_dist=-500)
四、键盘操作
自动化测试中,pywinauto 的keyboard模块提供了强大的键盘操作能力,其中keyboard.send_keys()可直接向当前获焦窗口发送按键序列。但实际自动化场景中,我们通常需要针对文本框、按钮等特定控件精准输入,而非依赖窗口的焦点状态。
from pywinauto.keyboard import send_keys
send_keys("1234567")
为满足精准输入需求,pywinauto 对键盘输入功能进一步封装,推出type_keys方法。该方法是 Edit、Button 等控件对象的专属方法,可直接作用于指定控件,确保输入精准,能避免焦点切换引发的输入错误,适配复杂界面的自动化操作。
语法:
type_keys(
keys, # 要输⼊的键序列,可以是普通字符、特殊键或组合键
pause = None, #每次按键后的延迟时间(秒)
with_spaces = False, # 如果为 True,则会在输⼊的字符串中保留空格。
with_newlines = False, #如果为 True,则会在输⼊的字符串中保留换⾏符。
...
)
向当前焦点窗⼝⾃动键⼊键或发送⽂本。
4.1输⼊⽂本
直接输⼊⽂本(⽀持Unicode字符):
from pywinauto import Application
app = Application(backend='uia').connect(process=32936)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
#输⼊⽂本内容
win.123("------type_keys------")
#保留换⾏符
win.type_keys("------type_keys------\n",with_newlines=True)
#保留空格
win.type_keys(" -----type keys----",with_spaces=True)
#延迟输⼊,避免输⼊过快导致内容不完整
win.type_keys("⼀⼆三四五六七",with_spaces=True)
4.2按键
使⽤{VK_CODE} 格式表⽰虚拟键码,例如:

示例代码:
from pywinauto import Application
app = Application(backend='uia').connect(process=32936)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
#发送⽂本和回⻋
win.type_keys("Hello World{ENTER}",with_spaces=True)
win.type_keys("Hello bit",with_spaces=True)
指定重复次数 可以为特殊键指定重复计数。
{ENTER 2} 表⽰按两次Enter键
#发送⽂本和回⻋
win.type_keys("Hello World{ENTER 2}",with_spaces=True)
win.type_keys("Hello bit",with_spaces=True)
转义特殊字符
使⽤{} 包裹特殊字符(如{+} ,{%} ,{^} )以避免被识别为修饰符
win.type_keys("1+2=3") # 错误:`+` 会被识别为 Shift
win.type_keys("1{+}2=3") # 正确
4.3⾃动化测试场景⽰例:微信发消息

1)⽤例设计 GUI⾃动化⽤例的设计主要基于UI(界⾯)测试和界⾯展⽰的功能来进⾏⽤例的设计。

2)代码实现
以⽤例"验证用户输⼊⽂本后点击发送按钮,消息是否能成功发送并显⽰在聊天窗⼝中"为例
# app = Application(backend="uia").start("D:\software\WeChat\WeChat.exe")
app = Application(backend="uia").connect(process=9768)
win = app.window(title="⽂件传输助⼿",handle=921080)
win.wait("visible")
#找到输⼊控件
edit = win.child_window(title="输⼊", control_type="Edit")
edit.wait("ready")
#点击消息框
edit.click_input()
#输⼊⽂本信息
edit.type_keys("⼩⽐特666")
#点击发送
win.child_window(title="发送(S)", control_type="Button").click_input()
#检查发送结果
win.child_window(title="⼩⽐特666",control_type="ListItem").texts()
掌握了如何发送微信消息后,可以跟玩得要好的朋友试试"消息轰炸机~"(可不敢到处发,⼩⼼被举报、拉⿊,甚⾄封号......)
五、菜单控件的操作
5.1 items()
返回对话框的菜单项,如果没有菜单项,则返回空列表
示例:获取菜单

from pywinauto import Application
app = Application(backend='uia').connect(process=38544)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
menu = win['应⽤程序']
print(menu.items())
结果:

5.2 item_by_index()
语法: item_by_index(idx) 查找索引指定的菜单项
idx :索引,从0开始
from pywinauto import Application
app = Application(backend='uia').connect(process=38544)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
menu = win['应⽤程序']
menu.item_by_index(0)
5.3 item_by_path()
语法 :item_by_path(path, exact=False)该方法用于查找路径指定的菜单项。
path:指定要选择的菜单项路径,格式为 "MenuItem->MenuItem->MenuItem...",每个 MenuItem 为对应层级的菜单文本;exact:设为True时要求菜单项名称与路径完全匹配,False时允许模糊匹配。
例如:
File->Export->ExportAsPNG
空格并不重要,所以你也可以写...
File -> Export -> Export As PNG
示例:
from pywinauto import Application
app = Application(backend='uia').connect(process=38544)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
menu = win['应⽤程序']
#menu.item_by_path(path="File->Save").click_input()
menu.item_by_path(path="File -> Save").click_input()
结果:

多层菜单选项的定位

点击 File 打开了 File 窗⼝,点击 Open Recent 会调起 Open Recent 窗⼝解决⽅案:先定位到 Open Recent 窗⼝再对ClearItems选项进⾏操作
app = Application(backend="uia").connect(process=25920)
#定位窗⼝
win = app.window(title_re=".*Sublime Text.*")
win.wait("visible")
menu_bar = win.child_window(title="应⽤程序", auto_id="MenuBar",
control_type="MenuBar")
#定位File菜单,并点击
file_menu = win.child_window(title="File",control_type="MenuItem")
#调起Open Recent窗⼝
menu_bar.item_by_path("File->Open Recent").click_input()
#定位到Open Recent窗⼝
openRecent_win = file_menu.child_window(title="Open Recent",
control_type="Window")
openRecent_win.wait("visible")
#定位Open Recent窗⼝Clear Items菜单项
openRecent_menu = openRecent_win.child_window(title="Open Recent",
control_type="Menu")
#⽅法⼀:通过菜单操作点击Clear Items
# clear_items = openRecent_menu.item_by_path("Clear Items")
#click_input不指定坐标会找控件的中间坐标,但是这⾥有偏差
# clear_items.click_input()
#⽅法⼆:通过定位控件并点击的⽅式
clear_items = openRecent_win.child_window(title="Clear Items", auto_id="31",
control_type="MenuItem")
point = clear_items.rectangle().mid_point()
mouse.move(coords=(point.x,point.y+30))
time.sleep(3)
mouse.click(coords=(point.x,point.y+30))
5.4 menu_select()
语法 :menu_select(path, exact=False)该方法用于查找并选择路径指定的菜单项。
path:指定菜单项路径,格式为 "MenuItem->MenuItem->MenuItem...",每个 MenuItem 为对应层级的菜单文本;exact:True要求菜单项名称与路径完全匹配,False允许模糊匹配。
注意:menu_select()需区分两类菜单栏 ------①系统菜单栏(父级为标题栏控件,含 "还原 / 移动 / 最小化" 等标准项);②应用程序菜单栏(多数情况下父级为对话框,是常规操作的目标菜单栏)。
File->Export->ExportAsPNG
空格并不重要,所以你也可以写...
File -> Export -> Export As PNG
示例:
from pywinauto import Application
app = Application(backend='uia').connect(process=38544)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
#win.menu_select(path="File->Save")
win.menu_select(path="File -> Save")
结果:

5.5⾃动化测试场景⽰例:批量创建⽂件
使⽤sublime_text来批量创建⽂件,针对创建⽂件的场景我们进⾏⽤例的设计,并编写对应的测试脚 本 )⽤例设计

2)代码实现以⽤例"验证保存⽂件后,⽂件是否正确写⼊到指定路径。"为例
from pywinauto import Application
app = Application(backend='uia').start("D:\software\Sublime Text
3\sublime_text.exe")
# app = Application(backend='uia').connect(process=28820)
win = app.window(title_re='.*Sublime Text.*')
win.wait("visible")
#批量创建五个⽂件
for i in range(1,3):
#输⼊内容
win.type_keys(f"创建第{i}个⽂件⽂件^s")
#等待保存⽂件窗⼝
save_win = win['另存为']
save_win.wait("visible")
#输⼊⽂件名称
filename = f"D:\\file\\GUITest\\test_{i}.txt"
save_win.child_window(title="⽂件名:", auto_id="1001",
control_type="Edit").type_keys(filename)
#点击保存
save_win.child_window(title="保存(S)", auto_id="1",
control_type="Button").click_input()
#检查创建结果
time.sleep(1)
assert os.path.exists(filename)
#创建空⽂件
win.type_keys("^n")

六、列表控件的操作
6.1 get_items()
获取列表视图中的所有项⽬。
示例:打印⽂件资源管理列表项

from pywinauto import Application
# app = Application(backend='uia').start("explorer.exe")
app = Application(backend='uia').connect(process=9628)
win = app.window(title_re='.*⽂件资源管理器')
win.wait('visible')
data_list = win.child_window(auto_id="HomeListView", control_type="List")
#打印列表项
print("items:",data_list.get_items())
6.2 item_count()
列表视图中的项数。
from pywinauto import Application
# app = Application(backend='uia').start("explorer.exe")
app = Application(backend='uia').connect(process=9628)
win = app.window(title_re='.*⽂件资源管理器')
win.wait('visible')
data_list = win.child_window(auto_id="HomeListView", control_type="List")
#打印列表项数量
print("items:",data_list.item_count())
6.3 get_item()
返回列表视图中的指定项⽬。 参数: row :可以是⾏的索引
from pywinauto import Application
# app = Application(backend='uia').start("explorer.exe")
app = Application(backend='uia').connect(process=9628)
win = app.window(title_re='.*⽂件资源管理器')
win.wait('visible')
data_list = win.child_window(auto_id="HomeListView", control_type="List")
#获取列表中第⼀项
print("items:",data_list.get_item(row=0))
⾃动化测试场景⽰例:微信发消息(进阶版)
此前实现的微信发消息自动化脚本虽流程完整,但存在明显问题:多次执行时,无法校验发送是否成功,且重复消息易因元素不唯一引发定位报错。结合列表操作优化后,正确思路为:
- 动态生成唯一消息文本,避免重复;
- 校验发送前后消息列表数量是否增加 1;
- 定位消息列表最后一条消息,验证其文本与发送的最新内容一致。
仍然以⽤例"验证用户输⼊⽂本后点击发送按钮,消息是否能成功发送并显⽰在聊天窗⼝中"为例
# app = Application(backend="uia").start("D:\software\WeChat\WeChat.exe")
app = Application(backend="uia").connect(process=9768)
win = app.window(title="⽂件传输助⼿",handle=921080)
win.wait("visible")
#获取发送消息之前消息数量
messageSizeBefore = win.child_window(title="消息",
control_type="List").item_count()
#找到输⼊控件
edit = win.child_window(title="输⼊", control_type="Edit")
edit.wait("ready")
#点击消息框
edit.click_input()
#输⼊⽂本信息--发送当前时间,精确到毫秒
# 获取当前时间
now = datetime.now()
edit.type_keys(now)
#点击发送
win.child_window(title="发送(S)", control_type="Button").click_input()
#检查发送结果
#1)获取发送消息之前消息数量
messageSizeAfter = win.child_window(title="消息",
control_type="List").item_count()
assert messageSizeAfter == messageSizeBefore+1 or
messageSizeAfter==messageSizeBefore+2
#2)获取发送的消息是否正确------消息内容作为title参数
win.child_window(title = formatted_time,control_type="ListItem")