2

I'm trying to browse to a file after i click the download button. But I though of writing a recursive function that finds controls in any window using AutomationElement library so hopefully i can find the nested controls in the open dialog window. This function is not working now. Please let me know where is the issue here or let me know if you have any suggestions.

The problem is that It never gets to the else statement and never ends. So i don't think it finds the element at all.

Here is the element highlighted that i'm trying to get using:

screenshot from inspect

Thanks

 private AutomationElement GetElement(AutomationElement element, Condition conditions, string className)
    {
        AutomationElement boo = null;
        foreach (AutomationElement c in element.FindAll(TreeScope.Subtree, Automation.ControlViewCondition))
        {
            var child = c;
            if (c.Current.ClassName.Contains(className) == false)
            {
                GetElement(child, conditions, className);   
             }
            else
            {
                boo = child.FindFirst(TreeScope.Descendants, conditions);
            }
        }

        return boo;
    }
Samy
  • 49
  • 9
  • You didn't mention in which way it doesn't work. Does nothing happen? Does it throw an exception? If so, provide the exception information. – Gediminas Masaitis Mar 04 '16 at 22:45
  • It never gets to the else statement and never ends. So i don't think it finds the element at all. Thanks – Samy Mar 04 '16 at 23:15
  • Well, don't ignore the return value of GetElement(). It of course will be the one you are looking for if it isn't null. – Hans Passant Mar 06 '16 at 18:51

1 Answers1

2

A tree walker would be better for this task.

Usage example:

// find a window
var window = GetFirstChild(AutomationElement.RootElement,
    (e) => e.Name == "Calculator");

// find a button
var button = GetFirstDescendant(window,
    (e) => e.ControlType == ControlType.Button && e.Name == "9");

// click the button
((InvokePattern)button.GetCurrentPattern(InvokePattern.Pattern)).Invoke();

Function to find a descendent element recursively with a delegate:

public static AutomationElement GetFirstDescendant(
    AutomationElement root, 
    Func<AutomationElement.AutomationElementInformation, bool> condition) {

    var walker = TreeWalker.ControlViewWalker;
    var element = walker.GetFirstChild(root);
    while (element != null) {
        if (condition(element.Current))
            return element;
        var subElement = GetFirstDescendant(element, condition);
        if (subElement != null)
            return subElement;
        element = walker.GetNextSibling(element);
    }
    return null;
}

Function to find a child element with a delegate:

public static AutomationElement GetFirstChild(
    AutomationElement root,
    Func<AutomationElement.AutomationElementInformation, bool> condition) {

    var walker = TreeWalker.ControlViewWalker;
    var element = walker.GetFirstChild(root);
    while (element != null) {
        if (condition(element.Current))
            return element;
        element = walker.GetNextSibling(element);
    }
    return null;
}
Florent B.
  • 41,537
  • 7
  • 86
  • 101
  • Thanks a lot for your answer. that is a great way to get the element.However, it still comes back null for me. The control is embedded and I don't see why it would find it. I'm adding a screenshot in my original post to give you an idea. – Samy Mar 07 '16 at 06:52
  • You first need to click on "Previous Location" so the "Address" control can be created. – Florent B. Mar 07 '16 at 07:51
  • Sorry im not understanding your answer @ florentbr. Should i try to get the "Address" combo box first? Thanks, – Samy Mar 07 '16 at 14:52
  • You are getting a null element because at the time you call the function, the control is not yet created by Windows. You never mentioned which control you were trying to interact with, so I guessed it was the "Address" combo box from the screenshot. You need to be more explicit on what you are trying to achieve here since the original question of this post is now answered. – Florent B. Mar 07 '16 at 16:18