Можно ли отключить автоматизацию пользовательского интерфейса для всего приложения WPF 4.0?

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

Это известная проблема для WPF 4.0, см., например:


Нам удалось воспроизвести эту проблему на машине с очень ограниченными характеристиками. Открытие окна WPF на этом компьютере требует:

  • 00:00:02 - без установленного программного обеспечения для автоматизации пользовательского интерфейса
  • 00:01:41 - с установленным ПО для автоматизации пользовательского интерфейса (для этого теста RoboForm)
  • 00:00:09 - с установленным программным обеспечением для автоматизации пользовательского интерфейса и применено исправление KB2484841

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


Следовательно, можно ли «отключить» автоматизацию пользовательского интерфейса для всего приложения WPF? Я знаю, что это можно сделать для каждого UserControl, но возможно ли это для приложения в целом?

Я пробовал код, приведенный в этом сообщении, но безуспешно.


Спасибо за уделенное время,
Коэн


person KoenJ    schedule 25.06.2013    source источник
comment
Автоматизация пользовательского интерфейса используется для доступности. Итак, если у клиента установлено программное обеспечение, которое ему нужно из-за каких-либо нарушений, вы хотите запретить ему использовать ваше программное обеспечение? Принимая некоторое замедление, не лучше ли было бы хотя бы обнаружить используемую автоматизацию, отсутствие установленного исправления и предложить пользователю (один раз или только каждые несколько перезапусков), что они должны установить ее?   -  person Damien_The_Unbeliever    schedule 25.06.2013
comment
Это внутреннее бизнес-приложение; такие сценарии не поддерживаются и выходят за рамки этого приложения.   -  person KoenJ    schedule 25.06.2013
comment
Не поддерживается ... пока вы не получите своего первого работника с инвалидностью. Это одна вещь, которую WPF сделал хорошо - он гарантирует, что все крайние случаи, такие как инвалидность, локализация и безопасность строк, подключены к тому времени, когда они вам нужны. Но такая подготовка имеет свою цену.   -  person srm    schedule 07.02.2014
comment
Проблема в том, что Microsoft так и не избавилась от нескольких последних ошибок в UIAutomation. Это приводит к сбою приложений, замедляет работу, вызывает бесконечные проблемы и намеренно затрудняет отключение. Это хреновая функция, лучше просто отключить ее вообще любыми возможными способами, по крайней мере, до тех пор, пока Microsoft не исправит нерешенные проблемы.   -  person Contango    schedule 09.10.2019


Ответы (5)


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

Попробовав все исправления и обходные пути, мы наконец нашли решение. Каждый элемент управления пользовательского интерфейса имеет объект AutomationPeer, который предоставляет свойства текущего элемента управления и его дочерних элементов управления. Клиент автоматизации пользовательского интерфейса использует эти AutomationPeer объекты для получения информации об элементах управления пользовательского интерфейса. Для большинства элементов управления пользовательского интерфейса в WPF имеется встроенный одноранговый класс автоматизации, и мы также можем создать собственный одноранговый класс.

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

public class CustomWindowAutomationPeer : FrameworkElementAutomationPeer
{
    public CustomWindowAutomationPeer(FrameworkElement owner) : base(owner) { }

    protected override string GetNameCore()
    {
        return "CustomWindowAutomationPeer";
    }

    protected override AutomationControlType GetAutomationControlTypeCore()
    {
        return AutomationControlType.Window;
    }

    protected override List<AutomationPeer> GetChildrenCore()
    {
        return new List<AutomationPeer>();
    }
}

Затем в главном окне переопределите метод OnCreateAutomationPeer:

protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
{
    return new CustomWindowAutomationPeer(this);
}

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

Дополнительные сведения см. В этой статье MSDN.

person ImthiyazPH    schedule 17.10.2014
comment
Просто сообщаю, что это решило мою проблему, за исключением использования только планшетов, использующих WPF ToolKit Datagrid. Ошибка и самая верхняя часть стека excepton: `System.InvalidOperationException: Рекурсивный вызов API однорангового узла автоматизации недопустим. at System.Windows.Automation.Peers.AutomationPeer.GetChildren () `Использование этой системы для возврата нового производного экземпляра AutomationPeer решило мои проблемы, и теперь все работает отлично. Спасибо. - person Mike Kshymensky; 11.03.2016
comment
Чтобы использовать: найдите в любом приложении WPF ‹Window. В результате будут найдены все файлы .xaml, унаследованные от класса Window. Затем в коде (файл .xaml.cs) добавьте код, который переопределяет OnCreateAutomationPeer(). Это частичный класс, поэтому вы также можете добавить : Window, чтобы прояснить, что этот частичный класс наследуется от Window. - person Contango; 18.02.2019
comment
Это не предотвратит выпадение поля со списком или всплывающего всплывающего окна для создания одноранговых узлов автоматизации и заставит остальную часть вашего приложения порождать одноранговые узлы автоматизации. - person Max Young; 26.06.2019

У нас была такая же проблема с элементами управления DevExpress. Нам не помогает ни один обходной код. И я полагаю, что нет никакого «переключателя» для отключения UI Automation. Но начиная с последних версий в DevExpress появился волшебный класс ClearAutomationEventsHelper, который делает некоторые трюки. Как я понял, идея состоит в том, чтобы очистить свойство AutomationEvents.Count (через Reflection) для элементов управления, вызывающих проблемы. Например, они вызывают этот метод в своих базовых элементах управления (из MeasureOverride) или каждый раз при создании однорангового узла автоматизации.

Если вы используете DevExpress, этот класс может стать серебряной пулей для вашего проекта. Мы смогли полностью избежать побочных эффектов проблем автоматизации пользовательского интерфейса в наших проектах WPF 4.0, и клиенты были очень довольны.

person Sergei B.    schedule 06.11.2013
comment
Чтобы все было правильно, класс DevExpress называется ClearAutomationEventsHelper. - person cremor; 07.11.2013
comment
Именно то, что я искал! ClearAutomationEventsHelper.IsEnabled = False удалил некоторые утечки памяти, которые имели место с DevExpress GridControl. - person Christian80; 07.01.2016

Попробуйте программирование культа карго:

WindowInteropHelper helper = new WindowInteropHelper(mainWindow);
        AutomationElement mainWindowAutomationElement = AutomationElement.FromHandle(helper.Handle);
        Automation.Automation.AddStructureChangedEventHandler(mainWindowAutomationElement, TreeScope.Descendants, AutomationFix);

      void AutomationFix(object sender, StructureChangedEventArgs e)
  {
            AutomationElement element = sender as AutomationElement;
    Automation.Condition condition = new PropertyCondition(AutomationElement.NameProperty, "!!");
    AutomationElement automationElement = element.FindFirst(TreeScope.Children, condition);
  }
person Frank R.    schedule 25.07.2013
comment
Этот код уже был опубликован в качестве ответа некоторое время назад, а затем был удален. Это был ты? Я скажу еще раз: хотя этот странный обходной путь может помочь некоторым людям, у которых уже работают клиенты автоматизации, он точно не отключает автоматизацию пользовательского интерфейса. - person cremor; 25.07.2013
comment
Нет, это не я ранее публиковал. Вам придется жить с обходными путями, пока Microsoft не решит, хотят ли они отключить автоматизацию пользовательского интерфейса, а я сомневаюсь, что они это сделают. - person Frank R.; 25.07.2013

Взгляните на эту статью:

Предотвращение доступа автоматизации пользовательского интерфейса к приложению

Говорят, что UIAccess flag может решить ваши проблемы!

Проверьте также эту статью, чтобы создать доверенный сертификат:

Проблема с манифестом и параметром uiAccess, установленным на true ...

person Emmanouil Chountasis    schedule 30.06.2013
comment
Флаг UIAccess по умолчанию ложен. - person cremor; 18.07.2013
comment
Добавление UI Access не решит проблему автоматизации. Доступ к пользовательскому интерфейсу предназначен для повышения привилегий программ специальных возможностей (например, экранного диктора и т. Д.), Чтобы они могли получить доступ к пользовательскому интерфейсу программ, которые в противном случае были бы заблокированы. - person Eric Brown; 18.07.2013

Вы пробовали следующее:

  1. Код автоматизации будет запущен только в том случае, если на машине запущены какие-либо клиенты автоматизации (например, программа чтения с экрана, вкладки на планшетах и ​​т. Д.). Итак, один из способов выйти из этой ситуации - закрыть любое из этих клиентских приложений автоматизации.

  2. Если это невозможно, то альтернативой является UIElementHelper.InvalidateAutomationAncestors будет занимать больше времени только в том случае, если дерево автоматизации для приложения является разреженным (происходит, если было отключено дерево автоматизации построения с использованием настраиваемого однорангового узла автоматизации окна), а визуальное дерево плотное. Таким образом, другое решение - отключить любой настраиваемый код автоматизации и позволить WPF построить полное дерево автоматизации. Это также должно ускорить UIElementHelper.InvalidateAutomationAncestors.

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

person Vlad Vlad    schedule 05.07.2013
comment
ветка MSDN, из которой вы скопировали этот ответ, связана с одним из вопросов, связанных в этом вопросе. Вам не кажется, что автор этого вопроса это уже читал? Кроме того, хотя он дает несколько советов о том, как улучшить ситуацию, на самом деле он не дает ответа на вопрос. - person cremor; 18.07.2013