【测试】pywinauto的简单使用(安装、常用对象、元素控件、鼠标操作、键盘操作)

1.说明

pywinauto是一个用于自动化Python 模块,适合Windows系统的软件(GUI),可以通过Pywinauto遍历窗口(对话框)和窗口里的控件,也可以控制鼠标和键盘输入,所以它能做的事情比之前介绍的pysimplegui更多

2.安装

一般使用pip安装就行了

pip install pywinauto

官网文档:https://pywinauto.readthedocs.io/en/latest/

3.Application

我们要控制软件的第一件事就是启动一个Windows软件,每一个软件(进程)都是一个Application对象

实例化Application对象的时候可以传入一个backend参数,可选值为win32(默认)和 uia

win32对应的框架:MFC、VB6、VCL、简单的 WinForms 控件和大多数旧的遗留应用程序
uia对应的框架:WinForms、WPF、商店应用程序、Qt5、浏览器
如果无法知道要测试的软件是属于哪种框架,可以使用 Inspect(对应uia)Spy++(对应win32) 看看,你看哪个显示得更全就选哪个。Inspect和Spy++需要自己安装一下

下面是Application对象的主要方法

方法常用参数说明
start()cmd_line、timeout、retry_interval通过cmd命令启动一个软件(进程)
connect()process、handle、path、timeout连接一个进程,一般是使用进程号(任务管理器可以看到)
top_window()/获取应用的顶层窗口
window()title、title_re、class_name、best_match获取单个窗口(WindowSpecification)
windows()title、title_re、class_name获取多个窗口(UIAWrapper)
is64bit()/是否64位应用
cpu_usageintervalCPU占用率
wait_cpu_usage_lower()threshold、timeout等待CPU占率小于某个阈值
active()()/搜索返回一个激活的窗口
kill()soft结束进程
wait_for_process_exit()timeout、retry_interval等待进程结束

举例,启动一个微信应用,通过进程号连接,进程号就是在任务管理器里详细信息看到的PID
在任务管理器查看进程号

from pywinauto import Applicationapp = Application(backend="uia")
# app.start(r"D:\Program Files (x86)\Tencent\WeChat\WeChat.exe")
app.connect(process=6556)
print("is64bit:", app.is64bit())
print("cpu_usage:", app.cpu_usage())
app.wait_cpu_usage_lower()
# app.active()  # 如果指定时间内不激活则报错
print("kill:", app.kill())
print("wait_for_process_exit:", app.wait_for_process_exit())

4.WindowSpecification

我们要获取窗口,一个窗口都是一个WindowSpecification对象,可以通过Application对象的window()方法获取,参数可以是title、classname或者best_match等,这都可以在inspect.exe上看到,不过需要注意的是inspect看到的Name其实对应的是window()的title参数
在这里插入图片描述

WindowSpecification对象常用的方法如下

方法常用参数说明
maximize()/最大化窗口
minimize()/最小化窗口
restore()/恢复窗口
close()/关闭窗口
get_show_state()/获取窗口状态,0正常1最大化2最小化
was_maximized()/当前是否最大化
draw_outline()colour、thickness给窗口画个框以便定位
print_control_identifiers()/打印所有子窗口和子元素(会打印出对应的control_type)
child_window()title、control_type获取子窗口
exists()timeout窗口是否存在
wait()wait_for, timeout等待窗口变成某个状态(exists、visible、enabled、ready、active)
wait_not()wait_for_not, timeout等待窗口不处于某个状态(exists、visible、enabled、ready、active)

举个栗子

dlg = app.window(class_name="WeChatMainWndForPC")
# dlg = app.window(title="微信")
print("get_show_state:", dlg.get_show_state())
print("was_maximized:", dlg.was_maximized())
dlg.print_control_identifiers()
dlg.draw_outline()
dlg.maximize()
dlg.restore()
dlg.minimize()
dlg.close()

5.元素控件

一个窗口里一般都会有各种各样的元素,比如说按钮 (Button)、编辑栏(Edit)、树状视图(Tree View)、复选框(CheckBox)、对话框(Dialog)、工具栏(Toolbar)、状态栏(StatusBar)、列表框(ListBox)、窗格(Pane)、菜单(Menu)、菜单栏(MenuItem)、静态内容(Static)、工具提示(ToolTips)、列表控件(ListView)、单选框(RadioButton)、组合框(ComboBox)、选项卡控件(TabControl)、组框 (GroupBox)、弹出菜单(PopupMenu)、头部(Header)等

因为控件类型太多了不能一个一个学习,但是它们都有一个 element_info 的属性,访问之后会返回一个继承于ElementInfo的对象(UIAElementInfo或HwndElementInfo),比较重要的属性或方法如下

方法或属性常用参数说明
name/元素的真实名(一般是title)
visible/元素是否可见
rich_text/元素的全名
rectangle/返回元素的位置以及宽高
class_name/类名
enabled/元素是否处于可用状态
parent/返回父元素
children()title、title_re、class_name、best_match返回符合要求的子元素(列表)
iter_children()title、title_re、class_name、best_match迭代符合要求的子元素(生成器)

这些元素除了有element_info可以获取一些元素的主要信息,它们还都被包装成一个Wrapper,所以也可以学一下BaseWrapper的常用方法和属性。其实BaseWrapper的方法基本上都是对ElementInfo进一步包装,我只列出部分方法,如下表

方法或属性常用参数说明
element_info/返回当前元素的ElementInfo对象
from_point()x、y通过坐标查找ElementInfo
class_name()/类名,实际是调用element_info.class_name
friendly_class_name()/友好的类名,同上
window_text()/元素的文本,实际是调用element_info.rich_text
is_visible()/元素是否可见,实际是调用element_info.visible
is_enabled()/元素是否可用,实际是调用element_info.enabled
rectangle()/元素的位置和宽高,实际是调用element_info.rectangle
process_id()/进程号,实际是调用element_info.process_id
draw_outline()colour、thickness给当前元素画个框
click_input()button、coords、double鼠标操作,实际是调用mouse模块的_perform_click_input()
type_keys()/键盘操作,实际是调用keyboard模块的send_keys()
dlg = app.window(class_name="WeChatMainWndForPC")
list_data = dlg.child_window(title="会话", control_type="List")
for item in list_data:print(type(item))element_info = item.element_infoprint(type(element_info))print("window_text:", )print("rich_text:", element_info.rich_text)print("name:", element_info.name)print("visible:", element_info.visible)print("rectangle:", element_info.rectangle)print("class_name:", element_info.class_name)print("enabled:", element_info.enabled)print("parent:", element_info.parent)print("children:", element_info.children())print("iter_children:", element_info.iter_children())if item.window_text() == "文件传输助手":item.click_input()item.type_keys("冰冷的希望")item.type_keys("{VK_RETURN}")print()

说明一下,每个控件元素都有对应的Wrapper,所以上面的方法也不一定都用,需要根据实际情况进行测试区分。另外,比较有用的click_input()type_keys()这两个方法分别用于操作鼠标和键盘(输入),下面我会单独拿出来说一下

6.鼠标操作

鼠标点击肯定离不开点击的位置,桌面就是一个坐标,左上角为坐标原点,往右是X轴正向,往下是Y轴正向。pywinauto提供了一个mouse模块用于鼠标操作,最核心的方法是_perform_click_input(),不过它是一个私有方法,我们调用的是基于它的封装方法,如下表

方法参数
click()button、coords单击鼠标某个键
double_click()button、coords双击鼠标某个键
right_click()coords单击鼠标右键
move()coords移动鼠标
press()button、coords按下鼠标
release()button、coords放开鼠标
scroll()coords、wheel_dist滚动鼠标滚轮
wheel_click()coords单击鼠标滚轮

参数说明:
参数button的默认值都是“left”,即鼠标左键,可选值有left、right、middle、move、wheel、x
参数coords 的默认值都是元组(0, 0),元组里的两个整数分别是X、Y轴的值
参数wheel_dist表示滚动的距离,大于0是向上滚动,小于0是向下滑动

举个栗子

from pywinauto import Application, mouseapp = Application(backend="uia")
app.connect(process=4352)
dlg = app.window(class_name="WeChatMainWndForPC")
list_data = dlg.child_window(title="会话", control_type="List")
for item in list_data:if item.window_text() == "文件传输助手":# item.click_input()rectangle = item.element_info.rectanglex = int((rectangle.left + rectangle.right) / 2)y = int((rectangle.top + rectangle.bottom) / 2)mouse.click(button='left', coords=(x, y))time.sleep(1)mouse.click("right", (x, y))time.sleep(1)mouse.move((x - 50, y))  # 往左边移动50个像素time.sleep(1)mouse.click(coords=(x, y))break

7.键盘操作

键盘操作主要是按下键盘上的按键,相关方法在keyboard模块,最最主要的是send_keys()方法,第一个参数keys就是我们需要按下的按键,其他参数比如说with_spaces、with_tabs、with_newlines、turn_off_numlock、set_foreground、vk_packet,一看就知道作用,而且都是布尔值,此处不进行举例

pywinauto支持的完整的按键可以在官方文档查看,https://pywinauto.readthedocs.io/en/latest/code/pywinauto.keyboard.html
下面我列举出的是一些比较常用的按键

按键符号说明
ShiftVK_SHIFT上档键
CtrlVK_CONTROL、VK_LCONTROL、VK_RCONTROLCtrl键、左右Ctrl键
AltVK_MENUAlt键
WindowsVK_LWIN、VK_RWIN左右win键
SpaceVK_SPACE空格键
backspaceBACKSPACE退格键
enterENTER回车键
escESC退出键
tableVK_TAB制表键
left、right、up、downVK_LEFT、VK_RIGHT、VK_UP、VK_DOWN上下左右方向键
f1~f24VK_F1、VK_F2…VK_F24f1到f24
capslockCAPSLOCK大写键

说明:
1.使用按键时需要搭配大括号,比如说按下回车键是 '{ENTER}' (是字符串)
2.在Windows平台默认是发送虚拟按键的,以VK_开头的按键,都是指虚拟按钮,如果不想使用虚拟按钮可以把VK_前缀去掉,把send_keys()的vk_packet参数改为False即可

单个按键按下抬起还不够,往往需要组合键,这时候就需要修饰符了,在大括号里可以使用downup控制按键什么时候按下和抬起,如果后面加上数字,表示按下多少次

list_data = dlg.child_window(title="会话", control_type="List")
for item in list_data:if item.window_text() == "文件传输助手":item.click_input()# item.type_keys("冰冷的希望")send_keys("   ")  # 随便输入字符串send_keys("{VK_CONTROL down} a {VK_CONTROL up}")  # 快捷键Ctrl+a(先按下Ctrl,再按下a,最后放开Ctrl)send_keys("{BACKSPACE}")  # 按下退格键删除文本send_keys("{. 6}")  # 按6次小数点send_keys("冰冷的希望{ENTER}")  # 输入文本,按下回车键

当然,很多时候使用downup修饰感觉不够简洁,所以pywinauto还提供了简化写法,使用+代替{VK_SHIFT},使用^代替{VK_CONTROL},使用%代替{VK_MENU}

send_keys('^a^c') # 按下Ctrl+a之后再按下Ctrl+c,即全选复制
send_keys('+{INS}') # 按下Shift+Ins键
send_keys('%{F4}') # 按下Alt+F4键

如果不想按下按钮,纯属想要输入纯字符串,那就需要取消转义了,注意修饰符和按钮的写法是不一样的

send_keys('{^}a{^}c{%}') # 输入字符串"^a^c%"而不是当成快捷键
send_keys('{{}ENTER{}}') # 输入字符串"{ENTER}"而不是按下回车键

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/58012.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Leetcode】124.二叉树中的最大路径和(Hard)

一、题目 1、题目描述 二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的根节点 root ,返回其…

解决ubuntu文件系统变成只读的方法

所欲文件变成只读,这种情况一般是程序执行发生错误,磁盘的一种保护措施 使用fsck修复 方法一: # 切换root sudo su # 修复磁盘错误 fsck -t ext4 -v /dev/sdb6 方法二: fsck.ext4 -y /dev/sdb6 重新用读写挂载 上面两种方法&…

龙蜥白皮书精选:SysAK—大规模复杂场景的系统运维利器

文/系统运维 SIG 01 概述 SysAK(System Analyse Kit)是龙蜥社区系统运维 SIG,通过对过往百万服务器运维经验进行抽象总结,而提供的一个全方位的系统运维工具集,可以覆盖系统的日常监控、线上问题诊断和系统故障修复…

checkstyle检查Java编程样式:隐藏属性

checkstyle可以使用HiddenField检查是否存在隐藏属性的行为:局部变量或者参数是否隐藏了在同一个类中的属性。 所谓隐藏属性,就是指局部变量、或者参数(例如构造器的参数、方法的参数)的名字和同一个类中的属性的名字相同。如果相…

【流量分析】Godzilla分析

一、哥斯拉流量的特点: 1.User-Agent (弱特征) 哥斯拉客户端使用JAVA语言编写,在默认的情况下,如果不修改User-Agent,User-Agent会类似于Java/1.8.0_121(具体什么版本取决于JDK环境版本)。但是哥斯拉支持…

XML—标记语言

什么是XML? Extensible Markup Language,可扩展标记语言。 那标记语言是什么? 用文字做标记表达一些效果或携带一些数据。比如:HTML、XML 我的理解:用倾盆大雨表达雨很大 那XML为什么说是可扩展的呢? 还…

vue2项目中表格的增删查改

我们在项目中经常会用到对于表格的增删查改操作,以下使用vue2elementui来实现表格的增删查改 表格的基本属性 基础表格如下:(其中需要注意的是当el-table元素中注入data对象数组后,在el-table-column中用prop属性来对应对象中的键名即可填入数据&#x…

PDF制作成翻页电子书

在日常工作中,大部分人使用的都是PDF文档发送给客户,但是PDF文档通常是静态的,缺乏交互性和视觉吸引力。那你有没有想过把它转换成翻页的电子书呢? 小编将告诉你操作步骤,非常简单 1.搜索FLBOOK在线制作电子杂志平台 …

【C修炼计划】卷壹 · 初识C语言

文章目录 卷壹 初识C语言一 C语言的起源二 C语言的特性三 C语言的应用范围四 C语言程序结构五 C语言书写规范六 C语言编译器安装附 参考资料 卷壹 初识C语言 一 C语言的起源 C语言的前生是B语言(BCPL,一种早期的高级语言)。下图描…

VMware虚拟机---Ubuntu无法连接网络该怎么解决?

在学习使用Linux系统时,由于多数同学们的PC上多是Windows系统,故会选择使用VMware创建一个虚拟机来安装Linux系统进行学习。 安装完成之后,在使用时总是会遇到各种各样的问题。本片随笔就主要针对可能出现的网络问题进行一个总结,…

物种气候生态位动态量化与分布特征模拟

在全球气候快速变化的背景下,理解并预测生物种群如何应对气候变化,特别是它们的地理分布如何变化,已经变得至关重要。利用R语言进行物种气候生态位动态量化与分布特征模拟,不仅可以量化描述物种对环境的需求和适应性,预…

限流算法深入

限流定义及目的 当系统流量达到系统或下游承受能力的阈值时对系统进行限流控制以防止系统或下游挂掉,减少影响面。 限流组成:阈值及限流策略。阈值是指系统单位时间接收到的请求qps总数;限流策略是指限流行业触发后对应的系统行为&#xff…

FPGA GTX全网最细讲解,aurora 8b/10b协议,HDMI板对板视频传输,提供2套工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 GT 高速接口解决方案3、GTX 全网最细解读GTX 基本结构GTX 发送和接收处理流程GTX 的参考时钟GTX 发送接口GTX 接收接口GTX IP核调用和使用 4、设计思路框架视频源选择IT6802解码芯片配置及采集动态彩条视频数据组包GTX aurora 8b/10b数据…

Django(5)-视图函数和模板渲染

Django 中的视图的概念是「一类具有相同功能和模板的网页的集合」 在我们的投票应用中,我们需要下列几个视图: 问题索引页——展示最近的几个投票问题。 问题详情页——展示某个投票的问题和不带结果的选项列表。 问题结果页——展示某个投票的结果。 投…

SVN 项目管理笔记

SVN 项目管理笔记 主要是介绍 SVN 管理项目的常用操作,方便以后查阅!!! 一、本地项目提交到SVN流程 在SVN仓库下创建和项目名同样的文件夹目录;选中本地项目文件,选择SVN->checkout,第一个是远程仓库项…

大数据Flink实时计算技术

1、架构 2、应用场景 Flink 功能强大,支持开发和运行多种不同种类的应用程序。它的主要特性包括:批流一体化、精密的状态管理、事件时间支持以及精确一次的状态一致性保障等。在启用高可用选项的情况下,它不存在单点失效问题。事实证明&#…

vue 学习笔记 简单实验

1.代码(html) <script src"https://unpkg.com/vuenext" rel"external nofollow" ></script> <div id"counter">Counter: {{ counter }} </div> <script> const Counter {data() {return {counter: 5}} } Vue.cr…

java-便签

--其实最痛的。不是离别。而是离别后的那些回忆。 java length( ) javalength中文占多长 1.一个中文字符或符号 2 个字节&#xff0c;一个英文字符或符号 1 个字节。 System.out.println("abc你好&#xff0c;".getBytes("gbk").length); System.out.pr…

【Linux】【驱动】驱动挂载的时候给驱动传递参数

【Linux】【驱动】驱动挂载的时候给驱动传递参数 绪论1.什么是驱动传参驱动传参就是传递参数给我们的驱动举例:2.驱动传参数有什么作用呢?3. 传递单个参数使用如下的数组4. 传递数组使用以下函数&#xff1a; 传递数字值代码指令 传递数组代码传递数组指令 绪论 1.什么是驱动…

如何拼接两个视频在一起?

如何拼接两个视频在一起&#xff1f;在度过一个美好周末的时候&#xff0c;我和朋友一起拍摄了两组视频&#xff0c;准备将两个视频合并成一个并发布到朋友圈。这个想法非常棒&#xff0c;但是我在第一步就遇到了麻烦&#xff1a;如何将这两个视频拼接在一起&#xff1f;这听起…