Microsoft UI Automation: вызов шаблонного исключения

Я пытаюсь нажать кнопку, используя шаблон вызова.

InvokePattern ipAddMPButton = (InvokePattern)aeAddMPButton.GetCurrentPattern(InvokePattern.Pattern);
        try
        {
            ipAddMPButton .Invoke();
        }
        catch (System.Runtime.InteropServices.COMException e)
        {
            // TODO
        }

Он выдает COMException, и я не могу понять, почему?

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


person HasnainMamdani    schedule 29.08.2014    source источник
comment
Кроме того, если это действительно выполняет операцию, то зачем беспокоиться, просто поймайте исключение и продолжите поток как есть.... Это на тот случай, если вы не получите надежное решение   -  person Ronak Agrawal    schedule 01.12.2014
comment
На самом деле у меня такое же поведение в приложении, которым я пытаюсь управлять с помощью UIAutomation. В моем случае это происходит с кнопками Winforms, которые открывают диалоговые окна Winforms (я полагаю, что это могут быть окна сообщений). Вызывающий поток зависает ровно на 1 минуту, а затем выдает исключение 0x80040201 — событию не удалось вызвать ни одного из подписчиков. Я проверил эти кнопки с помощью инструмента Inspect.exe, и, хотя я не вижу исключения, он ведет себя аналогично, а именно зависает на минуту после вызова Invoke (хотя вызов выполняется правильно).   -  person o_weisman    schedule 17.02.2016
comment
Это стандартная кнопка Winforms или что-то особенное? У вас есть воспроизводящий код? 0x80040201 — это UIA_E_ELEMENTNOTAVAILABLE, поэтому это может быть проблема состояния гонки, например, какой-то код (в приложении) уничтожает кнопку слишком рано, прежде чем все коммуникации между вашим приложением UIA и целевым приложением будут завершены.   -  person Simon Mourier    schedule 19.02.2016
comment
@SimonMourier На самом деле кнопка все еще видна за вновь открытым диалоговым окном, поэтому я предполагаю, что она не уничтожена, однако я подозреваю, что, поскольку это модальное диалоговое окно, остальная часть приложения не выдает сообщения и не может быть взаимодействовал с. Возможно, он блокируется до того, как сможет вернуть результат вызова Click() в поток UIAutomation?   -  person o_weisman    schedule 21.02.2016
comment
Это возможно, да. Это также может изменить его родительские отношения, что также может нарушить некоторые внутренние механизмы UIA. С UIA ничего не гарантируется, поскольку ваш код взаимодействует с чем-то, что не было специально разработано для взаимодействия с чем-либо. Однако, если у вас есть целевое приложение, это должно быть намного проще.   -  person Simon Mourier    schedule 21.02.2016
comment
Мне удалось воспроизвести подобное поведение, просто создав приложение Winforms с одной кнопкой. В обработчике Click я открываю простое окно сообщения. При использовании UI Automation Click() на кнопке она нажимается и открывается окно сообщения, но мое приложение зависает на несколько секунд, а затем сообщает об ошибке: Ошибка HRESULT E_FAIL была возвращена из вызова COM-компонента   -  person o_weisman    schedule 23.02.2016


Ответы (2)


На самом деле я обнаружил, что это уже обсуждалось здесь: invoke-in-virtual-pc?forum=windowsaccessibilityandautomation" rel="nofollow">https://social.msdn.microsoft.com/Forums/en-US/673bba3d-27b3-4374-b049-0d2e8ec5e462/hang-with- invokepattern-invoke-in-virtual-pc?forum=windowsaccessibilityandautomation . Подводя итог, можно сказать, что открытие модального диалога Winforms не очень хорошо работает с UIAutomation, поскольку оно не возвращается из команды Invoke и создает только модальное диалоговое окно, которое, конечно, не позволяет ему завершить операцию. Предлагаемое решение состоит в том, чтобы создать фоновый поток и активировать Invoke (или любую другую операцию) из этого потока. Я также предлагаю установить какой-то тайм-аут для завершения операции, поскольку в некоторых обстоятельствах это может быть длительным.

person o_weisman    schedule 23.02.2016

Попробуйте проверить aeAddMPButton.GetAllSupportedPatterns(), а затем попробуйте вызвать then..

person Ronak Agrawal    schedule 05.12.2014
comment
Есть ли у этого какое-то рациональное объяснение или это просто шарм по дереву? - person o_weisman; 23.02.2016
comment
Вызов GetAllSupportedPatterns() возвращает все поддерживаемые шаблоны для элемента. Вышеупомянутое исключение выдается, когда исключение не поддерживается или (в редких случаях) шаблоны не загружены. Сгенерированный список гарантирует, что вы проходите только через загруженные/поддерживаемые шаблоны, что позволяет избежать возможности возникновения исключения недопустимого шаблона. - person Ronak Agrawal; 24.02.2016
comment
Вы правы, но я считаю, что в данном случае проблема не в неподдерживаемом шаблоне, а в том, что кнопка не возвращается из вызова Invoke, как я цитировал в своем ответе ниже. Если бы шаблон не поддерживался, исключение не было бы перехвачено, поскольку GetCurrentPattern выдал бы исключение, а оно находится за пределами блока try. - person o_weisman; 24.02.2016
comment
Имеет смысл. Спасибо, что поделились этим! - person Ronak Agrawal; 24.02.2016