ITPub博客

首页 > 人工智能 > 机器学习 > PC端自动化测试实战教程-8-pywinauto操作

PC端自动化测试实战教程-8-pywinauto操作

投稿 机器学习 作者:ecclw459 时间:2026-01-07 16:13:47 0 删除 编辑

看下应用程序窗口的控件怎么操作呢???其实这个知识点前边已经有所涉及,只不过是一带而过,没有展开详细介绍。今天就来讲解和分享一下。PC端的应用程序的操作都是基于控件操作,如果要操作控件,我们就必须首先要找到控件对应的窗口,因此我们只需要基于控件查找对应的窗口框架,然后定位到控件即可操作了。那么跟随宏哥先来看一下常用的定位控件的方法。

2.常用定位控件方法

2.1通过层级查找控件相关方法

常用的定位控件的方法如下:

  • window(**kwargs) # 用于窗口的查找
  • child_window(**kwargs) # 可以无视层级的找后代中某个符合条件的元素===>【最常用】
  • parent() # 返回此元素的父元素,没有参数
  • children(**kwargs) # 返回符合条件的子元素列表,支持索引,是BaseWrapper对象(或子类)
  • iter_children(**kwargs) # 返回子元素的迭代器,是BaseWrapper对象(或子类)
  • descendants(**kwargs) # 返回符合条件的所有后代元素列表,是BaseWrapper对象(或子类)
  • iter_children(**kwargs) # 符合条件后代元素迭代器,是BaseWrapper对象(或子类)

2.2**kwargs 常用的一些参数

**kwargs 常用的一些参数如下:

class_name=None, # 类名
class_name_re=None, # 正则匹配类名
title=None, # 控件的标题文字,对应inspect中Name字段
title_re=None, # 正则匹配文字
control_type=None, # 控件类型,inspect界面LocalizedControlType字段的英文名
best_match=None,gov.yme.zuzb.info # 模糊匹配类似的title
auto_id=None, # inspect界面AutomationId字段,但是很多控件没有这个属性
parent=None,
process=None, # 这个基本不用,每次启动进程都会变化
top_level_only=True,
visible_only=True,
enabled_only=False,
handle=None,
ctrl_index=None,
found_index=None,
predicate_func=None,
active_only=False,
control_id=None,
framework_id=None,
backend=None,

3.查看窗口控件

要想操作窗口控件吗,我们需要先学会如何查看窗口框架,查看窗口的结构树。宏哥这里介绍两种比较常用的方法,而且这两种方法前边都有所介绍和讲解,这里简单演示一下即可。

3.1方法一(工具)

可以用inspect.exe 查看窗口的层级结构树。

1.双击启动inspect.exe软件,然后点击窗口的箭头按钮,如下图所示:

2.然后鼠标再次点击你要查看的窗口(宏哥要查看记事本的编辑区域的窗口结构树,点击箭头,然后再点击记事本的编辑区域)。如下图所示:

3.2方法二(代码)

可以通过 print_ctrl_ids()方法 (另外一个 print_control_identifiers() 功能一样,这个前边的文章已经介绍过也用过,今天介绍没有用过的)查看当前窗口下的控件。

3.2.1代码设计

3.2.2参考代码
# -*- coding:utf-8 -*-# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行# 2.注释:包括记录创建时间,创建人,项目名称。'''Created on 2025-04-18
@author: 北京-宏哥
北京宏哥(微信搜索:北京宏哥,关注宏哥,提前解锁更多测试干货!)
Project: PC端自动化测试实战教程-8-pywinauto操作应用程序窗口的控件(详细教程)'''# 3.导入模块from pywinauto import Applicationimport time# 通过窗口打开app = Application('uia').start("notepad.exe")
time.sleep(10)
app = Application('uia').connect(class_name="Notepad",visible_only=False)
win = app['无标题 - Notepad']
win.print_ctrl_ids()
3.2.3运行代码

1.运行代码,右键Run'Test',就可以看到控制台输出,如下图所示:

2.运行代码后电脑端的动作(启动记事本,打印窗口结构树)。如下图所示:

4.对比工具和代码查看的控件

因为要在记事本的编辑区域输入内容,所以我们需要操作编辑区域窗口的控件。但是此时宏哥发现工具查看的窗口结构树和代码打印的完全不一致,这难道因为宏哥的是Windows11系统吗???

1.工具查看记事本编辑区域,如下图所示:

2.代码打印记事本结构树,如下图所示:

D:\Python\python.exe D:/Demo/test.py
Control Identifiers:
Dialog - '无标题 - Notepad'    (L0, T0, R0, B0)
['无标题 - NotepadDialog', 'Dialog', '无标题 - Notepad', 'Dialog0', 'Dialog1']
child_window(title="无标题 - Notepad", control_type="Window")   | 
   | Pane - ''    (L-31992, T-31907, R-31297, B-31554)   | ['无标题Pane', 'Pane', '无标题Pane0', '无标题Pane1', 'Pane0', 'Pane1']   |    | 
   |    | Document - ''    (L-31992, T-31907, R-31297, B-31554)   |    | ['无标题Document', 'Document']   | 
   | Pane - ''    (L-31942, T-31988, R-31655, B-31956)   | ['无标题Pane2', 'Pane2']   |    | 
   |    | TabControl - ''    (L-31942, T-31988, R-31583, B-31948)   |    | ['TabControl添加新标签页', 'TabControl', '无标题TabControl']   |    | child_window(auto_id="Tabs", control_type="Tab")   |    |    | 
   |    |    | ListBox - ''    (L-31940, T-31988, R-31628, B-31948)   |    |    | ['无标题ListBox', 'ListBox']   |    |    | child_window(auto_id="TabListView", control_type="List")   |    |    |    | 
   |    |    |    | TabItem - '无标题. 未修改。'    (L-31937, T-31988, R-31630, B-31948)   |    |    |    | ['无标题. 未修改。', '无标题. 未修改。TabItem', 'TabItem']   |    |    |    | child_window(title="无标题. 未修改。", control_type="TabItem")   |    |    |    |    | 
   |    |    |    |    | Static - '无标题'    (L-31921, T-31978, R-31876, B-31959)   |    |    |    |    | ['Static', '无标题', '无标题Static', 'Static0', 'Static1']   |    |    |    |    | child_window(title="无标题", control_type="Text")   |    |    |    |    | 
   |    |    |    |    | Button - '关闭标签页'    (L-31681, T-31983, R-31641, B-31953)   |    |    |    |    | ['Button', '关闭标签页', '关闭标签页Button', 'Button0', 'Button1']   |    |    |    |    | child_window(title="关闭标签页", auto_id="CloseButton", control_type="Button")   |    |    | 
   |    |    | Button - '添加新标签页'    (L-31623, T-31982, R-31583, B-31952)   |    |    | ['添加新标签页', 'Button2', '添加新标签页Button']   |    |    | child_window(title="添加新标签页", auto_id="AddButton", control_type="Button")   |    | 
   |    | Pane - '记事本自动保存进度。下次打开记事本时,你的所有内容都将可用。'    (L0, T0, R0, B0)   |    | ['记事本自动保存进度。下次打开记事本时,你的所有内容都将可用。Pane', '记事本自动保存进度。下次打开记事本时,你的所有内容都将可用。', 'Pane3']   |    | child_window(title="记事本自动保存进度。下次打开记事本时,你的所有内容都将可用。", auto_id="TeachingTip", control_type="Pane")   | 
   | Pane - ''    (L-31992, T-31948, R-31436, B-31916)   | ['无标题Pane3', 'Pane4']   |    | 
   |    | Menu - ''    (L-31992, T-31948, R-31782, B-31908)   |    | ['Menu', '无标题Menu', 'Menu0', 'Menu1']   |    | child_window(auto_id="MenuBar", control_type="MenuBar")   |    |    | 
   |    |    | MenuItem - '文件'    (L-31987, T-31948, R-31927, B-31908)   |    |    | ['MenuItem', '文件MenuItem', '文件', 'MenuItem0', 'MenuItem1']   |    |    | child_window(title="文件", auto_id="File", control_type="MenuItem")   |    |    | 
   |    |    | MenuItem - '编辑'    (L-31917, T-31948, R-31857, B-31908)   |    |    | ['编辑', 'MenuItem2', '编辑MenuItem']   |    |    | child_window(title="编辑", auto_id="Edit", control_type="MenuItem")   |    |    | 
   |    |    | MenuItem - '查看'    (L-31847, T-31948, R-31787, B-31908)   |    |    | ['MenuItem3', '查看', '查看MenuItem']   |    |    | child_window(title="查看", auto_id="View", control_type="MenuItem")   |    | 
   |    | Button - '设置'    (L-31345, T-31948, R-31307, B-31908)   |    | ['设置Button', 'Button3', '设置']   |    | child_window(title="设置", auto_id="SettingsButton", control_type="Button")   |    | 
   |    | Dialog - ''    (L0, T0, R0, B0)   |    | ['Dialog2']   |    | child_window(auto_id="CowriterTeachingTip", control_type="Window")   | 
   | Pane - ''    (L-31992, T-31554, R-31436, B-31522)   | ['  行 1,列 1Pane', 'Pane5']   |    | 
   |    | Static - '  行 1,列 1'  gov.(L-31972, T-31544, R-31893, B-31524)   |    | ['Static2', '  行 1,列 1', '  行 1,列 1Static']   |    | child_window(title="  行 1,列 1", auto_id="ContentTextBlock", control_type="Text")   |    | 
   |    | Static - '0 个字符'    (L-31861, T-31544, R-31803, B-31524)   |    | ['Static3', '0 个字符', '0 个字符Static']   |    | child_window(title="0 个字符", auto_id="ContentTextBlock", control_type="Text")   |    | 
   |    | Static - ' 100%'    (L-31700, T-31544, R-31659, B-31524)   |    | ['Static4', ' 100%', ' 100%Static']   |    | child_window(title=" 100%", auto_id="ContentTextBlock", control_type="Text")   |    | 
   |    | Static - ' Windows (CRLF)'    (L-31616, T-31544, R-31505, B-31524)   |    | ['Static5', ' Windows (CRLF)Static', ' Windows (CRLF)']   |    | child_window(title=" Windows (CRLF)", auto_id="ContentTextBlock", control_type="Text")   |    | 
   |    | Static - ' UTF-8'    (L-31456, T-31544, R-31412, B-31524)   |    | ['Static6', ' UTF-8Static', ' UTF-8']   |    | child_window(title=" UTF-8", auto_id="ContentTextBlock", control_type="Text")   | 
   | TitleBar - ''    (L0, T0, R0, B0)   | [' UTF-8TitleBar', 'TitleBar']   |    | 
   |    | Menu - '系统'    (L-31991, T-31991, R-31963, B-31963)   |    | ['系统', 'Menu2', '系统Menu', '系统0', '系统1']   |    | child_window(title="系统", auto_id="MenuBar", control_type="MenuBar")   |    |    | 
   |    |    | MenuItem - '系统'    (L-31991, T-31991, R-31963, B-31963)   |    |    | ['系统2', 'MenuItem4', '系统MenuItem']   |    |    | child_window(title="系统", control_type="MenuItem")   |    | 
   |    | Button - '还原'    (L-31987, T-31999, R-31927, B-31973)   |    | ['Button4', '还原Button', '还原']   |    | child_window(title="还原", control_type="Button")   |    | 
   |    | Button - '最大化'    (L-31927, T-31999, R-31868, B-31973)   |    | ['Button5', '最大化', '最大化Button']   |    | child_window(title="最大化", control_type="Button")   |    | 
   |    | Button - '关闭'    (L-31868, T-31999, R-31808, B-31973)   |    | ['关闭', 'Button6', '关闭Button']   |    | child_window(title="关闭", control_type="Button")
Process finished with exit code 0

宏哥看了代码打印的根本没有工具查看的“文本编辑器”和Classname是“RichEditD2DPT”。这怎么搞......查了好几天资料也没有查到有用的或者能解决问题的方法。然后就打算放弃了...最后突然想到要不把那个“uia”换成“win32”试一下,但是总感觉不靠谱,因为工具查看的记事本是uia。不管了先试一下吧!

4.1参考代码

# -*- coding:utf-8 -*-# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行# 2.注释:包括记录创建时间,创建人,项目名称。'''Created on 2025-04-18
@author: 北京-宏哥
北京宏哥(微信搜索:北京宏哥,关注宏哥,提前解锁更多测试干货!)
Project: PC端自动化测试实战教程-8-pywinauto操作应用程序窗口的控件(详细教程)'''# 3.导入模块from pywinauto import Applicationimport time# 通过窗口打开app = Application('win32').start("notepad.exe")
time.sleep(10)
app = Application('win32').connect(class_name="Notepad",visible_only=False)
win = app['无标题 - Notepad']
win.print_ctrl_ids()

4.2运行代码

1.运行代码,右键Run'Test',就可以看到控制台输出,如下图所示:

2.出乎意料啊,从上图的控制台,竟然看到了工具查看的classname。不管三七二十一,宏哥觉得离胜利更进一步了。宏哥接着就要尝试能不能操作这个记事本编辑窗口的控件然后输入内容,如果可以就大功告成了。打印结构树如下:

D:\Python\python.exe D:/Demo/test.py
D:\Python\lib\site-packages\pywinauto\application.py:1076: RuntimeWarning: Application is not loaded correctly (WaitForInputIdle failed)
  warnings.warn('Application is not loaded correctly (WaitForInputIdle failed)', RuntimeWarning)
Control Identifiers:
Notepad - '无标题 - Notepad'    (L1011, T190, R1722, B684)
['Notepad', '无标题 - Notepad', '无标题 - NotepadNotepad']
child_window(title="无标题 -gov.zuqiu.mz.jrzb1.info Notepad", class_name="Notepad")   | 
   | Windows.UI.Composition.DesktopWindowContentBridge - 'DesktopWindowXamlSource'    (L1019, T615, R1696, B633)   | ['Windows.UI.Composition.DesktopWindowContentBridge', 'DesktopWindowXamlSourceWindows.UI.Composition.DesktopWindowContentBridge', 'DesktopWindowXamlSource', 'Windows.UI.Composition.DesktopWindowContentBridge0', 'Windows.UI.Composition.DesktopWindowContentBridge1', 'DesktopWindowXamlSourceWindows.UI.Composition.DesktopWindowContentBridge0', 'DesktopWindowXamlSourceWindows.UI.Composition.DesktopWindowContentBridge1', 'DesktopWindowXamlSource0', 'DesktopWindowXamlSource1']   | child_window(title="DesktopWindowXamlSource", class_name="Windows.UI.Composition.DesktopWindowContentBridge")   |    | 
   |    | Windows.UI.Input.InputSite.WindowClass - ''    (L1019, T615, R1019, B615)   |    | ['Windows.UI.Input.InputSite.WindowClass', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass', 'Windows.UI.Input.InputSite.WindowClass0', 'Windows.UI.Input.InputSite.WindowClass1', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass0', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass1']   |    | child_window(class_name="Windows.UI.Input.InputSite.WindowClass")   | 
   | Windows.UI.Input.InputSite.WindowClass - ''    (L1019, T615, R1019, B615)   | ['Windows.UI.Input.InputSite.WindowClass', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass', 'Windows.UI.Input.InputSite.WindowClass0', 'Windows.UI.Input.InputSite.WindowClass1', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass0', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass1']   | child_window(class_name="Windows.UI.Input.InputSite.WindowClass")   | 
   | Windows.UI.Composition.DesktopWindowContentBridge - 'DesktopWindowXamlSource'    (L1693, T283, R1711, B636)   | ['Windows.UI.Composition.DesktopWindowContentBridge2', 'DesktopWindowXamlSourceWindows.UI.Composition.DesktopWindowContentBridge2', 'DesktopWindowXamlSource2']   | child_window(title="DesktopWindowXamlSource", class_name="Windows.UI.Composition.DesktopWindowContentBridge")   |    | 
   |    | Windows.UI.Input.InputSite.WindowClass - ''    (L1693, T283, R1693, B283)   |    | ['Windows.UI.Input.InputSite.WindowClass2', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass2']   |    | child_window(class_name="Windows.UI.Input.InputSite.WindowClass")   | 
   | Windows.UI.Input.InputSite.WindowClass - ''    (L1693, T283, R1693, B283)   | ['Windows.UI.Input.InputSite.WindowClass2', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass2']   | child_window(class_name="Windows.UI.Input.InputSite.WindowClass")   | 
   | NotepadTextBox - ''    (L1019, T283, R1714, B636)   | ['无标题 - NotepadNotepadTextBox', 'NotepadTextBox']   | child_window(class_name="NotepadTextBox")   |    | 
   |    | Edit - ''    (L1019, T283, R1714, B636)   |    | ['Edit', '无标题 - NotepadEdit']   |    | child_window(class_name="RichEditD2DPT")   | 
   | Edit - ''    (L1019, T283, R1714, B636)   | ['Edit', '无标题 - NotepadEdit']   | child_window(class_name="RichEditD2DPT")   | 
   | Windows.UI.Core.CoreWindow - 'DesktopWindowXamlSource'    (L1019, T190, R1020, B191)   | ['DesktopWindowXamlSourceWindows.UI.Core.CoreWindow', 'Windows.UI.Core.CoreWindow', 'DesktopWindowXamlSource3']   | child_window(title="DesktopWindowXamlSource", class_name="Windows.UI.Core.CoreWindow")   | 
   | Windows.UI.Composition.DesktopWindowContentBridge - 'DesktopWindowXamlSource'    (L1069, T202, R1428, B242)   | ['Windows.UI.Composition.DesktopWindowContentBridge3', 'DesktopWindowXamlSourceWindows.UI.Composition.DesktopWindowContentBridge3', 'DesktopWindowXamlSource4']   | child_window(title="DesktopWindowXamlSource", class_name="Windows.UI.Composition.DesktopWindowContentBridge")   |    | 
   |    | Windows.UI.Input.InputSite.WindowClass - ''    (L1069, T202, R1069, B202)   |    | ['Windows.UI.Input.InputSite.WindowClass3', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass3']   |    | child_window(class_name="Windows.UI.Input.InputSite.WindowClass")   | 
   | Windows.UI.Input.InputSite.WindowClass - ''    (L1069, T202, R1069, B202)   | ['Windows.UI.Input.InputSite.WindowClass3', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass3']   | child_window(class_name="Windows.UI.Input.InputSite.WindowClass")   | 
   | Windows.UI.Composition.DesktopWindowContentBridge - 'DesktopWindowXamlSource'    (L1019, T242, R1714, B283)   | ['Windows.UI.Composition.DesktopWindowContentBridge4', 'DesktopWindowXamlSourceWindows.UI.Composition.DesktopWindowContentBridge4', 'DesktopWindowXamlSource5']   | child_window(title="DesktopWindowXamlSource", class_name="Windows.UI.Composition.DesktopWindowContentBridge")   |    | 
   |    | Windows.UI.Input.InputSite.WindowClass - ''    (L1019, T242, R1019, B242)   |    | ['Windows.UI.Input.InputSite.WindowClass4', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass4']   |    | child_window(class_name="Windows.UI.Input.InputSite.WindowClass")   | 
   | Windows.UI.Input.InputSite.WindowClass (L1019, T242, R1019, B242)   | ['Windows.UI.Input.InputSite.WindowClass4', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass4']   | child_window(class_name="Windows.UI.Input.InputSite.WindowClass")   | 
   | Windows.UI.Composition.DesktopWindowContentBridge - 'DesktopWindowXamlSource'    (L1019, T636, R1714, B676)   | ['Windows.UI.Composition.DesktopWindowContentBridge5', 'DesktopWindowXamlSourceWindows.UI.Composition.DesktopWindowContentBridge5', 'DesktopWindowXamlSource6']   | child_window(title="DesktopWindowXamlSource", class_name="Windows.UI.Composition.DesktopWindowContentBridge")   |    | 
   |    | Windows.UI.Input.InputSite.WindowClass - ''    (L1019, T636, R1019, B636)   |    | ['Windows.UI.Input.InputSite.WindowClass5', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass5']   |    | child_window(class_name="Windows.UI.Input.InputSite.WindowClass")   | 
   | Windows.UI.Input.InputSite.WindowClass - ''    (L1019, T636, R1019, B636)   | ['Windows.UI.Input.InputSite.WindowClass5', '无标题 - NotepadWindows.UI.Input.InputSite.WindowClass5']   | child_window(class_name="Windows.UI.Input.InputSite.WindowClass")
Process finished with exit code 0


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048957/viewspace-3107270/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2026-01-07

  • 博文量
    108
  • 访问量
    102108