crgmustang Ответов: 2

Проблема сохранения потока UIAutomation


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

Система.Время Выполнения.InteropServices.Исключение comexception (0x8001010D): исходящий вызов не может быть выполнено, так как приложение обрабатывает входящий синхронный вызов. (Исключение из HRESULT: 0x8001010D (RPC_E_CANTCALLOUT_ININPUTSYNCCALL))

Вот код, который выбирает элемент дерева:
AutomationElement elementNode = TreeWalker.RawViewWalker.GetFirstChild(SensorTreeCollection);
            SelectionItemPattern selectElement;

            while (elementNode != null)
            {
                try
                {
                    Console.Out.WriteLine("node of type " + elementNode.Current.ControlType.LocalizedControlType + " with name of " + elementNode.Current.Name);
                    sw.WriteLine(elementNode.Current.Name);

                    try
                    {
                        selectElement = elementNode.GetCurrentPattern(SelectionItemPattern.Pattern) as SelectionItemPattern;
                        selectElement.Select();
                        
                    }
                    catch (InvalidOperationException)
                    {
                        return;
                    }    
                }
                catch (Exception e)
                {
                    Console.Out.WriteLine("{0} Exception caught.", e);
                }
                elementNode = TreeWalker.ControlViewWalker.GetNextSibling(elementNode);
            }


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

Я расширил код, включив автоматику treewalker. Ошибка возникает при вызове selectElement.select ().

Я посмотрел на делегатов и метод Invoke, но не знаю, как адаптировать control.invoke() для использования с AutomationElement. Есть ли какой-то способ привести AutomationElement к элементу управления, чтобы он мог получить доступ к invoke?

2 Ответов

Рейтинг:
2

Elmue

UIAutomation очень критична к потокам!

1. ) Вы должны получить доступ к элементу AutomationElement всегда только из одного и того же потока.
2.) Поток должен быть STA-потока (однопотоковое подразделение)

Набор
нить.SetApartmentState(ApartmentState.STA);
прежде чем начать нить.

В противном случае вы можете получить эффект, что TreeWalker.GetFirstChild () или AutomationElement.FindAll() может возвращать только часть дочерних элементов AutomationElement (например, он может возвращать 3 из 10 дочерних элементов)

Эта ошибка отсутствующих детей очень трудно воспроизвести (и может произойти, например, на столе, но не на панели)

Я могу воспроизвести эту ошибку с помощью элемента управления DataGrid в приложении .NET, где возвращается только одна строка из 10 строк.


Dave Kreskowiak

Ты ведь знаешь, что этому вопросу больше двух лет, верно? Я сомневаюсь, что ОП все еще ищет ответ.

Elmue

И в чем же ваша проблема?
Вы знаете, что даже через 10 лет в будущем люди все равно найдут этот вопрос в Google?

Member 10481026

Я с 3-х лет в futur thx для ответа

Рейтинг:
16

Marc Koutzarov

Существует очень мало информации, чтобы дать вам подробный совет, но похоже, что у вас есть проблема с синхронизацией потоков. Найдите ключевое слово Invoke и delegate в c#.

пробовать эта статья для начала.


crgmustang

Спасибо за помощь, я добавил больше кода. Я проверил делегаты и метод invoke, но это для элемента управления, а не для элемента AutomationElement. Есть ли какой-то способ привести AutomationElement к элементу управления, чтобы я мог получить доступ к invoke?

Marc Koutzarov

http://msdn.microsoft.com/en-us/library/ms747211(v=против 110). aspx