UIAutomation Click button without making window take focus and GetCurrentPattern() returning unsupported pattern

StackOverflow https://stackoverflow.com/questions/22290668

質問

I have the handle of a window and what I want to do is click it's button named "Load Settings". I have 2 problems.

  • My first problem is when I call Invoke on a certain InvokePattern, it brings the window to focus and this is undesirable for my application.
  • My second problem is visible and documented in the comments towards the end of my following code:

    AutomationElement aeBot = AutomationElement.FromHandle(mbotSettingList.ElementAt(i).getWindowHandle());
    AutomationElement aeButtonLoadSettings = aeBot.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Load Settings"));
    InvokePattern ipClickLoadSettings = (InvokePattern)aeButtonLoadSettings.GetCurrentPattern(InvokePattern.Pattern);
    Thread invokeLoadSettingsThread = new Thread(ipClickLoadSettings.Invoke);
    InvokePattern ipClickOpen = null;
    AutomationElement aeOpenDialogEdit = null;
    AutomationElement aeButtonOpen = null;
    AutomationElementCollection aeDialogs = null;
    AutomationElement aeOpenDialog = null;
    ValuePattern vpOpenDialogEdit = null;
    
    //Using a thread to invoke the Load Settings button click because as a result of clicking Load Settings a dialog is opened and invoke doesnt return for nealy 10 seconds
    invokeLoadSettingsThread.Start();
    //We probably wont join() this thread because it goes on for far longer than we expect to be in this function
    
    //Get a collection of the Dialog windows that are direct children of the main window we have a handle to
    aeDialogs = aeBot.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "#32770"));
    
    while (aeDialogs.Count == 0)
    {
        //This while loop is to continue to check for the Open file dialog as it may take a little time to open
        aeDialogs = aeBot.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "#32770"));
        Thread.Sleep(250);
    }
    
    for (int j = 0; j < aeDialogs.Count; j++)
    {
        //There is usually only 1 child dialog window, but just make sure we have the correct one
        if (aeDialogs[j].Current.Name == "Open")
        {
            Debug.WriteLine("Found open dialog!");
            aeOpenDialog = aeDialogs[j];
            break;
        }
    }
    
    //Inside the Open window, the first Edit window is the one where the file name/path should be entered
    aeOpenDialogEdit = aeOpenDialog.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, "Edit"));
    
    //Set the value of the file name/path to the string variable "loadSettingsString"
    vpOpenDialogEdit = (ValuePattern)aeOpenDialogEdit.GetCurrentPattern(ValuePattern.Pattern); 
    vpOpenDialogEdit.SetValue(loadSettingsString);
    
    //******************************************PROBLEM BEGINING BELOW******************************************
    
    //Using multiple methods, we can successfully get a successful AutomationElement for the "Open" button in the Open file dialog
    aeButtonOpen = aeOpenDialog.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, "Open"));
    
    //aeButtonOpen = aeOpenDialog.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, "Cancel"));
    //Something to consider: If we assigned aeButtonOpen to the AutomationElement we find be looking for "Cancel" rather than "Open"
    
    Debug.WriteLine(aeButtonOpen.Current.Name + " button found!");
    //Prints "Open button found!"
    //If aeButtonOpen were assigned to "Cancel", this would print "Cancel button found!"
    
    ipClickOpen = (InvokePattern)aeButtonOpen.GetCurrentPattern(InvokePattern.Pattern);
    //GetCurrentPattern has returned null
    //If aeButtonOpen were assigned to "Cancel", this would NOT be null
    
    ipClickOpen.Invoke();
    //Invoke() on a null results in "Unsupported Pattern" exception
    //If aeButtonOpen were assigned to "Cancel", this would work and the Open file dialog would then be exited just as if cancel were clicked
    
役に立ちましたか?

解決

Use UIAVerify to look at the UIA tree of your application. Looking at your code, I suspect you're not retrieving the element you think you are. If the 'Open' element is a button, it should support the Invoke pattern.

Alternatively, you are opening a dialog and then immediately searching for a sub element of that dialog. It is possible that you are running into a reliability issue here where the UIA tree is still being created for that dialog. To check for this, add a sleep for one second and see if that resolves your issue. If this is the case, look into UIA structure changed events. Those events will let you synchronize your UIA test code against changes in the UIA tree.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top