28

We are developing a WPF 4.0 application for internal use.
On some clients, we are experiencing huge performance issues due to UI automation (these clients have software installed like tablet service pen, touch, ..).

This is a known issue for WPF 4.0, see for instance:


We've been able to reproduce this issue on a machine with very limited specs. Opening a WPF window on this machine takes:

  • 00:00:02 - without any UI automation triggering software installed
  • 00:01:41 - with UI automation triggering software installed (RoboForm for this test)
  • 00:00:09 - with UI automation triggering software installed, and hotfix KB2484841 applied

As you can see, installing hotfix KB2484841 is a huge improvement, but still not as fast as running without ui Automation triggering software installed.
Furthermore, we do not have much control over which software to install at the clients, so it's hard to roll out this fix for all clients.


Therefore, is it possible to "turn off" UI Automation for an entire WPF application? I know it can be done on a per-UserControl basis, but is it possible for the app as a whole?

I've tried the code provided in this post, but without success.


Thanks for your time,
Koen

Community
  • 1
  • 1
KoenJ
  • 1,093
  • 2
  • 13
  • 24
  • 3
    UI automation is used for accessibility. So if a client has software installed that they need because of any disabilities, you want to *prevent* them from being able to use your software? Accepting some slow down, would it not be better to at least detect the "Automation in use, no hotfix installed" and prompt the user (once, or only every few restarts) that they ought to get it installed? – Damien_The_Unbeliever Jun 25 '13 at 12:39
  • 2
    It's an internal business application; these kinds of scenarios are not supported and are out of scope for this application. – KoenJ Jun 25 '13 at 12:41
  • 3
    Not supported... until you get your first employee who has a disability. That's one thing WPF has done well -- it makes sure that all the edge cases, like disability and localization and string security, are all hooked up for that time you need them. But that preparation comes at a price. – srm Feb 07 '14 at 19:48
  • The problem is - Microsoft never got rid of the last few bugs for UIAutomation. It causes applications to crash, it slows things down, it causes endless problems, and it's intentionally made difficult to disable. It's a s*** of a feature, better to just disable it altogether by any means possible, at least until Microsoft fixes the outstanding issues. – Contango Oct 09 '19 at 09:02

5 Answers5

22

We hit the exact same issue mentioned in the question, where a UI automation client was impacting the performance of our WPF application.

After trying all the hot fixes and workarounds, finally we found a solution. Each UI control has an AutomationPeer object that exposes the properties of the current control and its child controls. The UI automation client uses these AutomationPeer objects to get the information about the UI controls. There are built-in automation peer class for most of the UI controls in WPF and we can also create a custom peer class.

The following is a custom automation peer class. Note that in the GetChildrenCore method, it is returning an empty list instead of the list of actual child controls.

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>();
    }
}

Then in your main window, override the OnCreateAutomationPeer method:

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

Now when the UI automation client tries to get the child controls of the main window, it gets back an empty list and so it cannot iterate through the rest of the controls.

Refer this MSDN article for more details.

Contango
  • 76,540
  • 58
  • 260
  • 305
ImthiyazPH
  • 299
  • 3
  • 7
  • 1
    Just posting to say that this resolved my issue with an exception using only tablets using WPF ToolKit Datagrid. Error and very top of the excepton stack were: ` System.InvalidOperationException: Recursive call to Automation Peer API is not valid. at System.Windows.Automation.Peers.AutomationPeer.GetChildren()` Using this system to return a new derived instance of the AutomationPeer resolved my issues and everything works perfectly now. Thanks. – Mike Kshymensky Mar 11 '16 at 16:40
  • To use: search any WPF app for " – Contango Feb 18 '19 at 14:51
  • 1
    This will not prevent the combo box fly out or the tool tip popup from generating automation peers and causing the rest of your application from spawning automation peers – Max Young Jun 26 '19 at 15:20
3

We had the same issue with DevExpress controls. Neither workaround code helps to us. And I suppose that there is not any "switch" to disable UI Automation. But since last versions DevExpress have magic ClearAutomationEventsHelper class that do some tricks. As I understood, the idea is to clear AutomationEvents.Count property (via Reflection) for controls that cause issue. E.g., they call this method in their base controls (from MeasureOverride), or each time automation peer created.

If you use DevExpress, this class can be silver bullet for your project. We able totally avoid side effects of UI Automation issues in our WPF 4.0 projects and customers were really happy.

Sergei B.
  • 138
  • 7
  • 2
    Just to get this correct, the DevExpress class is named `ClearAutomationEventsHelper`. – cremor Nov 07 '13 at 09:25
  • Just the thing I was looking for! ClearAutomationEventsHelper.IsEnabled=False removed some memory leaks we where having with DevExpress GridControl. – Christian80 Jan 07 '16 at 10:22
1

Try some cargo-cult programming:

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);
  }
Joe R.
  • 2,032
  • 4
  • 36
  • 72
  • This code was already posted as an answer some time ago and was then deleted. Was that you? I'll say it again: While this weird workaround might help some people that already have automation clients running, it for sure doesn't **disable** UI automation. – cremor Jul 25 '13 at 05:41
  • No, it wasn't me who previously posted it. You'll have to live with workarounds until Microsoft decides whether they want to provide disabling UI automation, which I doubt they will do. – Joe R. Jul 25 '13 at 16:37
0

Take a a look at this article :

Preventing UI Automation access to an application

It is said that UIAccess flag may be able to solve your problems!

Chack also this article so as to create a Trusted certificate :

Problem with manifest and uiAccess set to true...

  • The UIAccess flag is false by default. – cremor Jul 18 '13 at 09:15
  • Adding UI Access will not solve the automation issue. UI Access is there to raise the privilege of accessibility programs (like Narrator, etc.) so they can access the UI of programs that would otherwise be blocked. – Eric Brown Jul 18 '13 at 19:28
-1

Have you tried the following things:

  1. Automation code will be triggered only if there are any automation clients ( like screen reader, tabtip in tablet pcs, etc) running in the machine. So one way to get out of this situation is to close any of those automation client apps.

  2. If one is not feasible then an alternative is, UIElementHelper.InvalidateAutomationAncestors will take longer time only if automation tree for the app is sparse ( happens if had disabled building automation tree using custom window automation peer) and visual tree is dense. So another solution is disable any custom automation code and allow WPF to build complete automation tree. This should speed up UIElementHelper.InvalidateAutomationAncestors as well.

This is what I've found regarding your problem, also they said that they are aware of this issue and will try to fix it.

Vlad Vlad
  • 132
  • 2
  • 13
  • 1
    The [MSDN thread](http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/6c4465e2-207c-4277-a67f-e0f55eff0110/poor-wpf-application-performance-due-to-ui-automation-on-certain-machines) you copied this answer from is linked in one of the questions that are linked in this question. Don't you think the author of this question already read that? Also, while it provides some tips on how to improve the situation, it doesn't really answer the question. – cremor Jul 18 '13 at 12:53