python篇-pywinauto使用-PC端应用UI自动化
1- pywinauto 中的uia是什么意思?
在pywinauto库中,uia指的是UI Automation,这是Windows操作系统提供的一种技术框架,用于实现用户界面(UI)的自动化测试和辅助功能访问。UI Automation是微软从Windows Vista开始引入的核心技术,旨在为所有UI元素提供一致的编程接口,无论这些元素是由何种技术(如Win32、WPF、UWP等)实现的。
在pywinauto中,通过指定backend="uia",用户可以选择使用UI Automation作为底层引擎来与应用程序的UI元素进行交互。这为自动化测试提供了更广泛的支持,尤其是在处理现代Windows应用(尤其是使用WPF和UWP技术构建的应用)时更为有效。UI Automation后端相比传统的win32后端,提供了更丰富和高级的元素属性、控制模式(Control Patterns)以及事件支持,使得自动化脚本可以更加灵活和强大。
使用UI Automation后端,开发者可以更容易地定位和操作UI元素,如获取元素的属性、模拟鼠标和键盘操作、监听UI事件等,这对于创建复杂的自动化测试场景尤其有用。
2-pywinauto 中main_window.child_window()方法及参数详细介绍
parent_window.child_window(arguments)
其中,parent_window
是你已经获取到的窗口对象,arguments
是用于筛选子窗口的一系列关键字参数。
参数详解
child_window()方法接受多个关键字参数来精确地定位子窗口,常见的参数包括但不限于:
title: 字符串,控件的标题或文本。
class_name: 字符串,控件的类名。
control_type: 字符串,控件的类型(仅在UIA backend下有效)。
auto_id: 字符串,控件的自动化ID(AutomationId)。
name: 字符串,控件的名称属性,可能与标题或自动化ID不同。
backend: 字符串,指定后端类型,如 'win32' 或 'uia',默认自动选择。
process: 整数,指定目标窗口所在的进程ID。
enabled: 布尔值,是否只查找启用的控件。
visible: 布尔值,是否只查找可见的控件。
top_level_only: 布尔值,是否只在顶级窗口中查找。
found_index: 整数,当找到多个匹配项时,可以选择特定索引的匹配项。
control_id: 整数,控件的ID(Windows API中的控件ID)。
handle: 整数或ctypes.c_void_p,直接指定控件的句柄。
regex_title: 正则表达式对象或字符串,用于匹配标题的正则表达式。
regex_class_name: 同上,但用于匹配类名的正则表达式。
best_match: 字符串,用于best_match()逻辑,尝试匹配最接近的控件。
3-pywinauto 定位元素
方法一:1.可使用 inspect.exe来
方法二:这里我使用 dump_tree() 方法可以获取窗口的详细信息,包括控件的层次结构和属性。
print(dlgmax.dump_tree())
层次结构和属性如下
Dialog - 'XXXXXXX信息管理系统' (L579, T265, R1340, B775)
['XXXXXXX信息管理系统', 'Dialog', 'XXXXXXX信息管理系统Dialog', 'XXXXXXX信息管理系统0', 'XXXXXXX信息管理系统1']
child_window(title="XXXXXXX信息管理系统", auto_id="LoginForm", control_type="Window")
|
| Button - '忘记密码' (L1034, T674, R1096, B697)
| ['忘记密码Button', 'Button', '忘记密码', 'Button0', 'Button1']
| child_window(title="忘记密码", auto_id="btn_repwd", control_type="Button")
|
| Edit - '' (L855, T563, R1096, B582)
| ['', 'Edit', '0', '1', 'Edit0', 'Edit1']
| child_window(auto_id="tb_password", control_type="Edit")
|
| Edit - '密码' (L855, T513, R1096, B532)
| ['2', 'Edit2']
| child_window(title="密码", auto_id="tb_account", control_type="Edit")
|
| Static - '密码' (L810, T564, R849, B588)
| ['密码', 'Static', '密码Static', 'Static0', 'Static1']
| child_window(title="密码", auto_id="pwdTitleLbl", control_type="Text")
|
| Static - '账号' (L810, T514, R849, B538)
| ['Static2', '账号Static', '账号']
| child_window(title="账号", auto_id="accountTitleLbl", control_type="Text")
|
| Button - '登录' (L810, T631, R1096, B661)
| ['登录Button', '登录', 'Button2']
| child_window(title="登录", auto_id="btn_login", control_type="Button")
|
从上面可以得出登录的元素;这样就完成登录界面的UI自动化代码了
account=dlgmax.child_window(auto_id ="tb_account", control_type="Edit")
account.type_keys("admin")
pwd=dlgmax.child_window(auto_id = "tb_password", control_type = "Edit")
pwd.type_keys("888888")
dlgmax.child_window(title="登录",auto_id="btn_login", control_type="Button").click_input()
4-pywinauto 没有权限打开PC端应用,怎么解决?
raise AppStartError(message) pywinauto.application.AppStartError: Could not create the process "C:\Program Files (x86)\aaaa\xxxxxx信息管理系统\ybbbb.exe" Error returned by CreateProcess: (740, 'CreateProcess', '请求的操作需要提升。')
确保脚本本身以管理员身份运行
def is_admin(): try: return ctypes.windll.shell32.IsUserAnAdmin() except: return False if not is_admin(): # 重新启动脚本以管理员身份运行 ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1) sys.exit(0)
整体代码如下
import subprocess
from pywinauto import Application
import time
import ctypes
import sys
import io
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
if not is_admin():
# 重新启动脚本以管理员身份运行
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)
sys.exit(0)
try:
# 将标准输出重定向到文件
output_file = open('output.txt', 'w', encoding='utf-8')
sys.stdout = output_file
# 打开应用
app = Application(backend="uia").start(r'C:\Program Files (x86)\aaaaa\xxxxx管理系统\bbbb.exe')
print("应用启动成功")
# 等待主窗口出现
time.sleep(10) # 增加等待时间
dlgmax = app["xxxxxxx管理系统"]
if dlgmax.exists():
print("主窗口已找到")
else:
print("主窗口未找到")
raise Exception("主窗口未找到")
print(dlgmax.dump_tree())
account=dlgmax.child_window(auto_id ="tb_account", control_type="Edit")
account.type_keys("admin")
pwd=dlgmax.child_window(auto_id = "tb_password", control_type = "Edit")
pwd.type_keys("888888")
dlgmax.child_window(title="登录",auto_id="btn_login", control_type="Button").click_input()
# print(dlgmax.dump_tree())
except Exception as e:
print(f"Error: {e}")
finally:
# 恢复标准输出,并确保使用 UTF-8 编码
output_file.close()
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
input("按回车键退出...")
作者:weixin_42811974