Windows技巧:轻松连接多进程窗口之一
此文章来源于项目官方公众号:“AirtestProject”
版权声明:允许转载,但转载必须保留原链接;请勿用作商业或者非法用途
一、前言
在连接windows
窗口的时候,有些同学会遇到一个应用但是打开了几个不同的进程窗口,但是在AirtestIDE搜索窗口只有一个或寻找窗口名称都是统一名称的时候,又应该如何处理呢?那么今天我们一起来探讨下这个问题吧~
二、获取windows应用进程相关信息方式
在需要获取windows
应用进程的相关信息,我们需要确保我们的python
环境中含有下面几种库,建议在本地的python
环境中进行修改,并将AirtestIDE
的python
环境更换为本地的python
环境。
pip install psutil
pip install pywinauto
2.1 获取windows所有进程
可以获取本地计算机上所有正在运行的进程的类实例,并返回一个迭代器,我们可以将我们需要查询的指定参数传入括号内,会以字典的形式去创建一份进程表。
for proc in psutil.process_iter(['pid', 'name', 'create_time']):
print(proc.info)
2.2 获取进程异常类
有三种不同的获取进程的异常类,我们可以通过异常处理进行跳过或输出报错等。
#当在当前进程列表中找不到具有给定 pid的进程时,或者当进程不再存在时,由类方法引发。
psutil.NoSuchProcess(pid, name=None, msg=None)
#当由于权限不足而拒绝执行操作的权限时, 由类方法引发。
psutil.AccessDenied(pid=None, name=None, msg=None)
#如果超时并且进程仍然存在,则通过方法引发。
psutil.TimeoutExpired(seconds, pid=None, name=None, msg=None)
2.3 判断进程是否有界面
可以通过使用pywinauto
库下的 findwindows.find_window(process=pid)
获取窗口句柄去进行判断,当获取的窗口句柄长度大于0时,则证明该进程有界面。
def has_gui(pid):
try:
windows = findwindows.find_windows(process=pid)
return len(windows) > 0
except Exception as e:
return False
2.4 使用进程pid
去连接特定进程
我们可以通过在连接设备时传入pid
号进行连接特定的进程窗口,就算有多个进程窗口,我们也可以根据不同窗口的进程pid
去进行连接测试。
dev = connect_device(f"Windows:///?process=pid")
当然,我们除了这个也还有其他连接窗口的句柄,可以根据自己的需求去实现连接,更多的Windows
小技巧也可以查看我们教程文档:
https://airtest.doc.io.netease.com/IDEdocs/3.2device_connection/5_windows_connection/
# 连接一个Windows窗口,窗口句柄为123456
dev = connect_device("Windows:///123456")
# 连接一个Windows窗口,窗口名称匹配某个正则表达式
dev = connect_device("Windows:///?title_re=Unity.*")
# 连接windows桌面,不指定任何窗口,对应IDE的桌面模式
dev = connect_device("Windows:///")
三、使用案例
上面提供了一些获取应用进程的方式,以及查询选择pid
的方法,那么我们实际运用起来的效果会是怎么样的呢?
可以看到,我们可以先通过应用的进程名,去全局搜索本地是否已开启该应用,然后通过找到的进程,逐一排查有窗口界面的应用进程pid
,再连接上对应的应用窗口并调出来,并进行测试操作。
参考代码如下:
# -*- encoding=utf8 -*-
__author__ = "Airtest"
import psutil
from pywinauto import findwindows
from airtest.core.api import *
# 获取所有进程信息
def get_process_info(process_name):
process_info_list = []
# 获取本地目前所有的进程并查找我们需要连接的进程
for proc in psutil.process_iter(['pid', 'name', 'create_time']):
#将需要搜索的进程信息加入到列表里,并在搜索结束后返回列表
try:
if process_name.lower() in proc.info['name'].lower():
process_info_list.append(proc.info)
#当出现异常时,直接跳过
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return process_info_list
# 判断进程是否有界面
def has_gui(pid):
try:
#利用pid去获取窗口句柄,当窗口句柄大于0时,则证明该进程有窗口界面
windows = findwindows.find_windows(process=pid)
return len(windows) > 0
except Exception as e:
return False
# 选择特定进程
def select_process(process_info_list):
for proc_info in process_info_list:
# 判断进程是否有界面
if has_gui(proc_info['pid']):
return proc_info['pid']
return None
# 连接到特定进程并进行操作
def connect_and_operate(process_info):
if process_info:
try:
# 连接到特定进程窗口
dev = connect_device(f"Windows:///?process={process_info}")
print("Target process found.")
# 连接后可以进行自动化操作,例如点击、输入等,这里仅做截图操作
sleep(3.0)
snapshot(msg="当前界面截图", quality=90)
#遇到异常后,将异常信息抛出
except Exception as e:
print(f"Error during connecting or operating: {e}")
else:
print("No target process found.")
if __name__ == "__main__":
process_name = "有道云笔记.exe" # 示例应用程序名称
# 获取所有目标应用的进程信息
process_info_list = get_process_info(process_name)
print(f"Found processes: {process_info_list}")
# 选择特定进程(通过动态获取对应进程的pid,进行连接)
selected_process = select_process(process_info_list)
print(f"Selected process: {selected_process}")
# 连接到特定进程并进行操作
connect_and_operate(selected_process)
四、小结
我们今天介绍了几个在windows
上有关获取进程相关信息的方法,分别是:
1、获取所有进程
2、获取进程异常类
3、判断进程是否有界面
4、使用进程pid
去连接特定进程
通过上述方法,我们可以通过应用进程的相关信息,去实现更多的windows窗口连接方式,如果你有更好的连接窗口的小技巧,也欢迎在评论区或私信告诉我们。如果在测试的过程中,遇到了问题,或者有任何想要深入了解的知识点,欢迎在官方交流群里告诉我们或者提交issue,也欢迎大家投稿其他不同的使用小技巧。
AirtestIDE下载:airtest.netease.com/
Airtest 教程官网:airtest.doc.io.netease.com/
搭建企业私有云服务:airlab.163.com/b2b
官方答疑 Q 群:526033840