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

news2024/11/24 8:47:31

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 Application

app = 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_info
    print(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, mouse

app = 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.rectangle
        x = 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.coloradmin.cn/o/913851.html

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

相关文章

鲁图中大许少辉博士八一新书《乡村振兴战略下传统村落文化旅游设计》山东省图书馆典藏

鲁图中大许少辉博士八一新书《乡村振兴战略下传统村落文化旅游设计》山东省图书馆典藏

数据宽度、KEIL汇编和GNU汇编的区别

数据宽度 DCB data control byte(byte) DCW data control half word(short) DCD data control word(int) DCQ data control (long)KEIL汇编和GNU汇编的区别 IDA关于please position the cursor within a funtion的解决 我是在C/C++反编译中出现的问题,因为在动态调试的时候…

ctfshow-web11

0x00 前言 CTF 加解密合集CTF Web合集 0x01 题目 0x02 Write Up 这里要求输入的passwd和session必需要相当,那么我们只要让密码和session都为空即可。 以上

Vue的Ajax请求-axios、前后端分离练习

Vue的Ajax请求 axios简介 ​ Axios,是Web数据交互方式,是一个基于promise [5]的网络请求库,作用于node.js和浏览器中,它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生node.js http模块, 而在…

%f占位符

介绍: %f ,用来输出实数(包括单双精度),以小数形式输出。 通常情况下,当输入的数值或者打印的数值是float类型数据时,使用%f ,当然在精度更高的double数据类型下,也可以…

行业追踪,2023-08-22

自动复盘 2023-08-22 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…

Windows端口占用CMD关闭端口(8080被占用)

一、背景 作为一名开发,我们是不是经常遇到端口被占用了,比如80,8080等,但是我们却不知道是那个工程启动,对小白来说,估计会很苦恼,网上搜索也很麻烦处理,网上推荐也是如下步骤&…

springBoot防止重复提交

自定义注解AOPRedis 自定义注解 package com.wzw.config.anno;import java.lang.annotation.*;/*** 自定义注解防止表单重复提交*/ Target(ElementType.METHOD) // 注解只能用于方法 Retention(RetentionPolicy.RUNTIME) // 修饰注解的生命周期 Documented public interface …

2024届校招:校招必须知道的三件事

校招提前知 提到校招,不少同学受到“金九银十”的影响,认为九、十月份是进行校招的时间段。但实际上,校招的时间越来越提前,上周陆续有央企、国企开启了24届提前批的招聘,打响了24届校招的第一枪。今天给大家整理了校…

Google Guava Cache的使用

1、前言 Google Guava Cache是Google Guava库中的一个缓存框架,用于缓存计算结果、数据或资源,提高程序访问效率和响应速度。Guava Cache具有以下特点: ①可配置性:Guava Cache支持多种缓存参数的配置,例如缓存大小、…

全流程R语言Meta分析核心技术教程

详情点击链接:全流程R语言Meta分析核心技术教程 一,Meta分析的选题与检索 1、Meta分析的选题与文献检索 1)什么是Meta分析? 2)Meta分析的选题策略 3)精确检索策略,如何检索全、检索准 4)文献的管理与清洗,如何制定文…

【Winform学习笔记(八)】通过委托实现跨窗体传值

通过委托实现跨窗体传值 前言正文1、委托及事件2、通过委托实现跨窗体传值的步骤1.在子窗体中定义委托2.在子窗体中声明一个委托类型的事件3.调用委托类型事件4.在实例化子窗体后,子窗体订阅事件接受方法5.实现具体的事件 3、具体示例4、完整代码5、实现效果 前言 …

cesium官网链接打不开

经常遇到cesium官网的某些链接打不开的情况 比如下面是一个cesium官网的blog链接 https://cesium.com/blog/2015/08/10/Introducing-3D-Tiles/ 可是打不开 解决办法: 把url中所有大写的字母都改成小写 大写的地方用黑体标出:Introducing-3D-Tiles …

SAP SPL(Special Ledger)之注释行项目-Noted Items

财务凭证过账里常见的SPL特殊总账标识根据业务主要有三种,BoE-billing of exchange: 汇票业务,包括商业汇票和银行汇票;Down Payment,预付款业务,包括供应商和客户预付款和申请;其它,一般是保证…

2022年12月 C/C++(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题:鸡兔同笼 一个笼子里面关了鸡和兔子(鸡有2只脚,兔子有4只脚,没有例外)。已经知道了笼子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物。 时间限制:1000 内存限制:65536 输入…

高压放大器在液晶弹性体中的应用研究

液晶弹性体是一种有机高分子材料,具有良好的可控变形性能和反应速度,因此在显示器、光学器件等领域得到了广泛的应用。高压放大器作为一种电子设备,可以将输入信号进行放大,从而为液晶弹性体的驱动提供足够的强度。下面安泰电子将…

安捷伦DSO9404A示波器

DSO9404A DSO9404A 是 Agilent 的 4 GHz、4 通道数字示波器。随时间测量电子电路或组件中的电压或电流信号,以显示幅度、频率和上升时间等。应用包括故障排除、生产测试和设计。 壹捌叁贰零玖壹捌陆伍叁 附加的功能: 带宽:4 GHz 4个频道 大…

连接校园网或需要认证的网,认证页面弹不出来解决方案

网络设置 在设置中,找到网络和Internet; 左侧选择状态,右侧选择更改适配器选项; 选择需要认证的那个适配器 右键打开属性 勾上ipv4 和 ipv6 (ipv6 不是必须的) 打开ipv4的属性 按照如下进行设置 关闭代理 发现认证…

MySQL详细安装与配置

免安装版的Mysql MySQL关是一种关系数据库管理系统,所使用的 SQL 语言是用于访问数据库的最常用的 标准化语言,其特点为体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,在 Web 应用方面 MySQL 是最好的 RDBMS(Relation…

lab5 lazy

文章目录 Eliminate allocation from sbrk()Lazy allocationtaskhints实现 Lazytests and Userteststaskhints实现 Eliminate allocation from sbrk() 第一个任务是去阻止sysproc.c中的sys_sbrk()函数真的分配内存,只需要增p->sz即可 一行代码注释即可 uint64…