Невозможно получить доступ к элементам приложения win32 с использованием идентификатора с помощью pywinauto

Я новичок в автоматизации тестирования на основе рабочего стола Windows, а также новичок в python, потратив некоторое время, pywinauto оказался очевидным выбором для тестирования приложений на основе Windows с использованием python.

Я использую 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]")'

Я использовал инструмент подкачки, но он почему-то не предоставляет доступных элементов управления и не использует inspect.exe для проверки имен классов и т. д.

Я проверил различные другие способы, такие как использование findwindows, findwindows.find_element для дочернего окна, чтобы каким-то образом щелкнуть одну кнопку (не хотел использовать координату), а затем щелкнуть по вкладке, но ни один из них не дал мне подходящий элемент управления, например что я мог найти, используя какой-то платный инструмент, такой как Test Complete.

Интересно, можно ли сделать что-то вроде ниже, используя pywinauto

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

На данный момент единственное, что я могу сделать, это открыть приложение и с помощью оболочки закрыть или свернуть приложение.

Любое предложение будет высоко оценено.


person arin    schedule 28.02.2017    source источник
comment
Если вы успешно используете Inspect.exe, вам нужно использовать backend='uia'. Это может быть более полезным для современных приложений. Дополнительные сведения о серверных компонентах см. в Руководстве по началу работы.   -  person Vasily Ryabov    schedule 01.03.2017
comment
@VasilyRyabov, спасибо за указание. С помощью упомянутого подхода теперь я могу получить uiawrapper. Не знаю, как получить доступные элементы управления из uiawrapper. Прошел через ссылку большинство доступных методов, таких как uiawrapper .expand() приводит к ошибке указателя NULL COM. Интересно, я что-то пропустил?   -  person arin    schedule 01.03.2017
comment
Каков результат app.window(title="Start Application - XXX 2.3").print_control_identifiers()? С backend='uia' конечно.   -  person Vasily Ryabov    schedule 01.03.2017
comment
@VasilyRyabov, на выходе получается огромная трассировка стека с примерно 15-20 слоями :) .. с помощью которой я могу как-то переходить окно за окном, чтобы получить доступ к последней кнопке, которую я хочу. Но я не могу сделать что-то подобное Aliases.XXX.HwndSource_mainWindow.mainWindow.SelectApplicationControl.Grid.allApplicationsListView.ContentcontrolDemoappapplication.Click(), что намного приятнее и очень читабельно. Когда я использовал TestComplete для целей тестирования, чтобы увидеть, как он получает доступ кнопки/вкладки.   -  person arin    schedule 01.03.2017
comment
Это не трассировка стека, а дерево элементов управления. Вы можете скопировать и вставить имя возможного атрибута из второй строки описания каждого элемента управления в этом огромном выводе. Например, здесь вы можете использовать несколько имен из этого списка: [u'Size on disk:', u'Size on disk:Static', u'Static4']. Конечно, это должно быть исправлено, чтобы соответствовать ограничениям имени атрибута, скажем, dlg.Size_on_disk_Static.window_text().   -  person Vasily Ryabov    schedule 01.03.2017
comment
Также обратите внимание, что магия разрешения атрибутов должна работать через иерархию. Таким образом, вы можете опустить некоторые уровни, и он должен искать элемент управления внутри поддерева.   -  person Vasily Ryabov    schedule 01.03.2017
comment
И еще один важный момент: спецификация окна может быть многоуровневой, но UIAWrapper не может делать доступ к атрибутам более низких уровней. Сначала вам нужно выяснить, что такое спецификация окна и как она находит оболочку.   -  person Vasily Ryabov    schedule 01.03.2017


Ответы (1)


Просто подытожу комментарии здесь:

  • Если вы успешно используете Inspect.exe, вам нужно использовать backend='uia'. Это может быть более полезным для современных приложений. Дополнительные сведения о серверных компонентах см. в Руководстве по началу работы.

  • Огромный вывод print_control_identifiers() - это не трассировка стека, а дерево элементов управления. Вы можете скопировать и вставить имя возможного атрибута из второй строки описания каждого элемента управления в этом выводе. Например, здесь можно использовать несколько имен из этого списка:

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

    Конечно, это должно быть исправлено, чтобы соответствовать ограничениям имени атрибута, скажем, dlg.Size_on_disk_Static.window_text().

  • Также обратите внимание, что магия разрешения атрибутов должна работать через иерархию. Таким образом, вы можете опустить некоторые уровни, и он должен искать элемент управления внутри поддерева.

  • И еще один важный момент: спецификация окна может быть многоуровневой, но UIAWrapper не может делать атрибутный доступ к более низким уровням. Сначала вам нужно выяснить, что такое спецификация окна и как она находит оболочку.

person Vasily Ryabov    schedule 03.03.2017
comment
Спасибо. теперь я получаю поток. Для поиска оболочки я использую UiaMeta.find_wrapper, который предоставляет сведения об оболочке. Что касается нажатия на uiawrapper, я получаю разные ответы: для одной кнопки (control_type=button), которая является uiawrapper, я могу щелкнуть ее, но другая кнопка, где control_type=Text, я получаю, что uiawrapper не поддерживает щелчок, что на самом деле , когда я проверил детали API uiawrapper. Затем мне интересно, что было бы хорошим подходом, чтобы щелкнуть элемент управления control_type, который является текстовым, но интерактивным элементом? - person arin; 03.03.2017
comment
Вы можете использовать .invoke(), который может иметь другое значение для некоторых элементов, поэтому мы оставили его как invoke() для общего случая. - person Vasily Ryabov; 03.03.2017
comment
Некоторая дополнительная информация была бы полезна. Я попытался сделать info_button.wrapper_object().invoke() , но получил доступ к указателю NULL COM; pywinauto.uia_defines.NoPatternInterfaceError - person arin; 03.03.2017
comment
Если у кнопки нет InvokePattern (см. свойство InvokePatternSupported в Inspect.exe), вы также можете использовать .click_input(). Хотя для этого требуется активный рабочий стол, он всегда доступен для каждого элемента управления. - person Vasily Ryabov; 04.03.2017