pywinauto 无法解析 TreeItem 控件
复制本地路径 | 在线编辑
结论:放弃吧,就是解析不了,用了很多方法,就是不行。
问题
解析的时候,无法把 TreeItem 如 combobox、lineedit 等解析出来,只能得到 treeitem,所以用不了各种控件的特有方法。
经测试,并不奏效的尝试
修改源码
- 修改 GUI 程序的源码,使用 TreeView + Delegate,而不是 TreeWidget,经过测试,无效果。
- 修改 GUI 程序的源码,添加子节点,使用各种方法如
setItemsExpandable、setData等等,经过测试,都没有效果。 - 修改 GUI 程序的源码,添加 Accessible 信息,或者增加许多和 Accessible 属性有关的设置、各种方法(不列举了),经过测试,都没有效果。
DLL 注入
这样可以直接访问 QT 源码中的各个组件。放弃吧,千万不要尝试这条路。我之前居然花了一些时间尝试这样。第一步是写出 ClickButton(const char*) 或者 FindButton(const char*) 这样的函数。也不知道写的对不对。但最关键的是,第二步进行注入就失败了,现代的系统怎么可能让你这么容易注入呢,有管理员权限也没用,可能被防护软件阻止了。而且细细想想,这种方法完全是走偏了。
正确尝试
识别后用鼠标+键盘
根据文本去寻找组件,然后还是老老实实鼠标和键盘去操作。虽然 TreeItem 无法识别出正确的组件,比如下图中我们没法识别出 checkbox,但是可以通过提取文本,来得到 TreeItem,得到 Item 之后,可以用鼠标和键盘去点击或者输入。

# ! 遍历搜索,为什么不直接 child_window: 因为 pywinauto 不能识别出 treeitem
def item_idx_in_tree(mode_str, now_tree):
for idx, now_item in enumerate(now_tree):
now_text = now_item.texts()[0].replace(' ', '')
if now_text == mode_str:
return idx
return -1
print('Finding... ', child_name)
now_tree = dlg.child_window(title="Attribute Setting").TreeView.roots()
idx = item_idx_in_tree(child_name, now_tree)
if idx >= 0:
print("Found: ", child_name, "\n")
return now_tree[idx]
多个程序并行
如果并行去做?因为涉及到了鼠标和键盘,所以没办法并行。这种情况只能老老实实用虚拟机。
修改程序架构:GUI 程序的正确写法
最本质的解决方式,就是要修改程序架构,GUI 程序增加一个通信层,这是唯一的正路。而且架构也要注意了:一定要 GUI 和协议层分离!
GUI <--> 协议层 API <--> 更深层次的业务逻辑
GUI 一定不能和协议层耦合,否则到时候如果想要外层脚本控制 GUI 自动运行时,此时会有阻塞。
- 协议层暴露各种方法接口,然后 GUI 去调用或者外层脚本调用
- 协议层完成各种方法后,需要向 GUI 层输出信号,GUI 得到信号后才会修改 GUI 状态
- 如何实现,GUI 启动之后,调用我的脚本去自动化修改 GUI?GUI 启动之后,协议层 API 也就启动了,然后就可以调用了
所以协议层一定要是通过网络通信来完成。因为这是跨进程的,即:
- 我启动了 GUI 之后,会把协议层也启动;并且协议层开始不断循环,接收信号→操作→发送信号
- 此时可以启动新的脚本,脚本通过网络通信来和协议层交互
还有一个关键:协议层是一个独立个体,也就是说 GUI 启动的时候,如果发现没有协议层会启动协议层;如果脚本启动的时候,发现没有协议层,也会启动协议层。