pywinauto find_elements() returns ElementNotFoundError

pywinauto find_elements() returns ElementNotFoundError

我正在尝试使用 pywinauto 和 Python 3.6 自动化一个简单的应用程序。该应用程序有一个 Windows "Open" 对话框,我想单击 "Cancel" 按钮:

我使用 SWAPY 获取按钮的 class_name 和 control_id 属性。

现在的问题是,当我使用这些参数调用 find_element() 方法时,它会引发 ElementNotFoundError。这是我的代码:

cancel_button = pywinauto.findwindows.find_element(class_name="button", control_id=2)

我试过(class_name="button", control_id="2")(class_name="Button", control_id=2),但它们都给出相同的错误。我试图在此对话框中找到的任何其他元素都会出现同样的问题。

那么如何使用从 SWAPY 读取的属性呢?我没有发现官方的 pywinauto 文档非常有用。很多东西都没有解释清楚。

编辑: 我决定不使用 find_elements 方法,而是使用 find_windows() 来获取“打开”对话框的句柄。

w_open_handle = pywinauto.findwindows.find_windows(title=u'Open', class_name='#32770')[0]

然后我使用这个句柄得到一个 WindowSpecification 对象:

w_open = app.window_(handle=w_open_handle)

然后我打电话给:

w_open['Cancel'].click()

这行得通。现在我想在 "File name:" 编辑框中输入一个文件名,然后单击打开按钮打开该文件。所以我这样做:

w_open['File name:'].type_keys("abc.txt")

这行得通。我使用 print_control_identifiers() 打印出控件标识符,并获得了“打开”按钮的名称。所以使用 draw_outline() 我在它外面画了一个边界,它显示了正确的按钮。

w_open['SplitButton6'].draw_outline()

但是在 'SplitButton6' 上调用 .click() 方法会引发 WindowSpecification class 没有 'click' 方法 错误。知道是什么原因造成的吗?该错误似乎具有误导性,因为 WindowSpec class 确实有一个 .click 方法。

正确答案是您错过了 top_level_only=False(默认情况下是 True,因为更高级别 API 至少调用它两次)。那么您可能有 2 个控件符合此条件(可能来自不同的应用程序)。 find_element 是低级函数。不推荐直接使用(代码太长,有很多坑,上级考虑到了API)。

>>> pywinauto.findwindows.find_element(class_name="Button", control_id=2, top_level_only=False)
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
  File "...\pywinauto\findwindows.py", line 98, in find_element
    raise exception
ElementAmbiguousError: There are 2 elements that match the criteria {'class_name': 'Button', 'control_id': 2, 'top_level_only': False}

>>> pywinauto.findwindows.find_element(class_name="Button", title='Cancel', top_level_only=False)
<win32_element_info.HwndElementInfo - 'Cancel', Button, 395554>

使用更高级别 API(Application 对象和 WindowSpecifications 在指南中描述)你不应该关心将进程 ID、后端名称和其他东西传递给 find_element每次。

P.S。在我看来,SWAPY 可以得到显着改进,但去年没有维护。我希望将来用更小的代码库和 MS UI 自动化支持重新编写它。但目前全自动脚本生成器优先级更高


编辑:

此按钮 w_open['SplitButton6'].draw_outline() 可能会被检测为一般 HwndWrapper 对象而不是 ButtonWrapper。你可以用这个检查它:

w_open['SplitButton6'].wrapper_object()

这正是入门指南(您说您已阅读)中所写的内容。

幸运的是,您可以对任何控件使用方法 .click_input()

w_open['SplitButton6'].click_input()

我可以说更多:WindowSpecification 没有 click 方法。这是动态实例化的 ButtonWrapper 方法。例如,这些语句的工作方式相同(但 Python 可以隐藏 .wrapper_object() 调用):

w_open['SplitButton6'].wrapper_object().click_input()
w_open['SplitButton6'].click_input()

Getting Started Guide 中也有描述。请阅读整个指南。你会发现很多有用的高级东西。如果仍然不清楚,我可以就一些极端情况提出建议。