Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What could cause (managed) UIAutomation to get a self reference when enumerating children

Have come across a dialog where a particular group of controls seems to be recursively referencing itself. Of note the application provides an MSAA / LegacyAccessible interface to the UI Automation framework, such apps seem to be more fragile and seem to cause all sorts of grief, may or may not be relevant to this issue though.

So as an example, searching a window using FindFirst, if the element is before this self referencing element all is well, if it is after then this goes on forever pooling memory in both the client and server.

Condition condition = new PropertyCondition(AutomationElement.IsPasswordProperty, true);
AutomationElement myPassword = element.FindFirst(TreeScope.Descendants, condition);

Working through direct children has the same issue

private void WalkControlElements(AutomationElement rootElement, ...)
{
    AutomationElementCollection childElements = rootElement.FindAll(TreeScope.Children, Automation.ControlViewCondition);

    foreach (AutomationElement elementNode in childElements)
    {
        WalkControlElements(elementNode, ... );
    }
}

Working through TreeWalker.ControlIViewWalker has the same issue

private void WalkControlElements(AutomationElement rootElement, ...)
{
    AutomationElement elementNode = TreeWalker.ControlViewWalker.GetFirstChild(rootElement);

    while (elementNode != null)
    {
        WalkControlElements(elementNode, ... );
        elementNode = TreeWalker.ControlViewWalker.GetNextSibling(elementNode);
    }
}

It should look like

  group ""
     button "Home"

What it is looking like

  group ""
     button "Home"
     group ""
        button "Home"
        group ""
           button "Home"
           group ""
              button "Home"
              group ""
                 ...

An interesting thing though is that some other tools don't seem to be having this trouble. Inpsect in either MSAA or UIAutomation mode doesn't grow an infinite tree.

So this leaves me wondering, what is it I'm doing wrong, or have not done that allows Inspect to work, but causes me an infinite recursion. It appears from other SO comments that Inspect uses the native interface, and the issue might be with the Managed interface.

If it cannot be fixed, can such a scenario be identified?

Keeping a list of the controls during the recursive function, A simple check for having seen the element before didn't result in a match.

ref List<AutomationElement> controls
  if (controls.Contains(autoElement)) 
like image 750
Greg Domjan Avatar asked Nov 18 '25 08:11

Greg Domjan


1 Answers

In my opinion, we need add more a valid method here to validate an element (says node in control chain in case we use TreeWalker to navigate control). A valid method can based on the following way (one of or combination of them):

  • Method GetUpdatedCache with input CacheRequest::Current: This method will try creat a clone of object if object is exist actually. Otherwise, an exception may be raised.
  • Try to GetHashCode of element/object: In some specific case, an
    invalid element will have negative value/hash code.

In additional, it seems that UI Automation technology rely on specific platform (of Application) (not entirely), so we can determine which platform application belongs to (say win32, winform, wpf..) before we figure out solution to validate.

If we have a valid method strictly enough, we can do 2 things:

  • Retrieve actual element to work on.
  • Avoid of breaking down if API got problem when navigate to an invalid node itself.
like image 156
kansaz Avatar answered Nov 20 '25 21:11

kansaz