【问题标题】:Unable to access elements of win32 application using identifier using pywinauto无法使用 pywinauto 使用标识符访问 win32 应用程序的元素
【发布时间】:2017-02-28 18:36:17
【问题描述】:

我对基于 Windows 桌面的测试自动化非常陌生,而且对 python 也很陌生,在花了一些时间之后,pywinauto 变成了使用 python 进行基于 Windows 的应用程序测试的明显选择。

我正在使用 pywinauto 来访问演示应用程序中的元素。我浏览过相关文档和stackoverflow问答,GitHub上的示例。这就是我所做的

app = Application(backend="win32").start(r"C:\XXX\Bin\XXX.exe")

while not app.Windows_():
    time.sleep(1)

if app.window(title="Start Application - XXX 2.3").Exists():
    app.window(title="Start Application - XXX 2.3").PrintControlIdentifiers() 

我得到的输出是这样的

b'\nHwndWrapper[XXX.exe;;ebf7c21b-5fef-4eb7-a562-3d36735e7519] - \'Start Application - XXX 2.3\'    (L668, T45, R1786, B969)\n[\'HwndWrapper[XXX.exe;;ebf7c21b-5fef-4eb7-a562-3d36735e7519]\', \'Start Application - XXX 2.3HwndWrapper[Zen.exe;;ebf7c21b-5fef-4eb7-a562-3d36735e7519]\', \'Start Application - XXX 2.3\']\nchild_window(title="Start Application - XXX 2.3", class_name="HwndWrapper[XXX.exe;;ebf7c21b-5fef-4eb7-a562-3d36735e7519]")'

我使用了 swapy 工具,但不知何故不提供可用的控件和使用 inspect.exe 来检查类名等。

我检查了各种其他方式,例如使用 findwindows、findwindows.find_element 作为子窗口,以某种方式单击一个按钮(不想使用坐标),然后按标签单击,但没有一个给我合适的控制,就像我可以使用一些付费工具(如测试完成)找到的。

想知道,是否可以使用 pywinauto 执行以下操作

Aliases.XXX.HwndSource_mainWindow.mainWindow.leftToolAreaControl.ToolAreaTabItem.TabControl.ClickTab("Acquisition")

目前,我唯一能做的就是打开应用程序,然后使用包装器关闭或最小化应用程序。

任何建议将不胜感激。

【问题讨论】:

  • 如果你使用Inspect.exe成功,你需要使用backend='uia'。这可能对现代应用程序更有帮助。有关后端的更多详细信息,请参阅Getting Started Guide
  • @VasilyRyabov,感谢您的指出。通过上述方法,现在我能够获得 uiawrapper。不确定如何从 uiawrapper 获得可用的控件。经历过link 大多数可用的方法,如 uiawrapper.expand(),导致 NULL COM 指针错误。想知道,我错过了什么吗?
  • 它不是堆栈跟踪,而是控制树。您可以从这个巨大输出中每个控件描述的第二行复制和粘贴可能的属性名称。例如,here 您可以使用此列表中的多个名称:[u'Size on disk:', u'Size on disk:Static', u'Static4']。当然,应该更正它以符合属性名称限制,比如dlg.Size_on_disk_Static.window_text()
  • 另请注意,属性解析魔术应该跨层次结构工作。所以你可以省略一些级别,它应该搜索子树内的控件。
  • 还有一件更重要的事情:窗口规范可以是多级的,但UIAWrapper 不能对较低级别进行属性访问。首先,您需要弄清楚什么是窗口规范以及它如何找到包装器。

标签: pywinauto


【解决方案1】:

这里只是总结一下cmets:

  • 如果你使用Inspect.exe成功,你需要使用backend='uia'。这可能对现代应用程序更有帮助。有关后端的更多详细信息,请参见Getting Started Guide

  • print_control_identifiers() 的巨大输出不是堆栈跟踪,而是控制树。您可以从该输出中每个控件描述的第二行复制和粘贴可能的属性名称。例如,您可以在此处使用此列表中的多个名称:

    [u'Size on disk:', u'Size on disk:Static', u'Static4']

    当然,应该更正它以符合属性名称限制,比如dlg.Size_on_disk_Static.window_text()

  • 还要注意,属性解析魔法应该跨层次结构起作用。所以你可以省略一些级别,它应该搜索子树内的控件。

  • 还有一件更重要的事情:窗口规范可以是多级的,但 UIAWrapper 不能对较低级别进行属性访问。首先,您需要弄清楚什么是窗口规范以及它如何找到包装器。

【讨论】:

  • 谢谢。现在我得到了流量。为了查找包装器,我使用了 UiaMeta.find_wrapper,它提供了包装器的详细信息。关于点击 uiawrapper,我得到了不同的响应:对于一个按钮(control_type="button"),它是 uiawrapper,我可以点击它,但是另一个按钮,control_type="Text",我得到 uiawrapper 不支持点击;这是事实,当我检查 uiawrapper api 详细信息时。然后,我想知道单击“文本”但可单击元素的 control_type 的好方法是什么?
  • 您可以使用.invoke(),这可能对某些元素有其他含义,因此我们将其保留为invoke(),以用于一般情况。
  • 更多信息会有所帮助。我尝试做 info_button.wrapper_object().invoke() ,但获得 NULL COM 指针访问; pywinauto.uia_defines.NoPatternInterfaceError
  • 如果按钮没有 InvokePattern(参见 Inspect.exe 中的InvokePatternSupported 属性),您也可以使用.click_input()。虽然它需要活动桌面,但它始终可用于每个控件。
猜你喜欢
  • 2022-07-09
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-30
  • 2020-12-19
  • 1970-01-01
  • 2021-01-21
相关资源
最近更新 更多