none
How to select an item in combobox in F# for UI automation

    Question

  • invalid operation at

    let pattern : SelectionPattern = LoginNameComboBox.GetCachedPattern(SelectionPattern.Pattern) :?> SelectionPattern <- error when run

    let LoginNameComboBox : AutomationElement = LoginWin.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "cboUserID"));
    if LoginNameComboBox = null then
        Console.WriteLine("No LoginNameComboBox")
    else
        Console.WriteLine("Got LoginNameComboBox")
    let pattern : SelectionPattern = LoginNameComboBox.GetCachedPattern(SelectionPattern.Pattern) :?> SelectionPattern <- error when run
    let selectedItems = pattern.Cached.GetSelection();
    let selectedItem = selectedItems.[0]

    Friday, March 30, 2012 6:43 AM

All replies

  • What kind of runtime exception do you have there?

    I suppose that casting operator gives you an error, so maybe you should cast to different pattern (ex. SelectionItemPattern etc.) I think you can find out real object type in debugger.


    Petr

    Friday, March 30, 2012 12:34 PM
  • do not know why null reference error

    http://stackoverflow.com/questions/5814779/selecting-combobox-item-using-ui-automation

    let GetSpecifiedPattern(element : AutomationElement, patternName : string) : AutomationPattern =
        let supportedPattern = element.GetSupportedPatterns() <--- error
        let mutable p : AutomationPattern = null
        for pattern in supportedPattern do
            if pattern.ProgrammaticName = patternName then
                p <- pattern
        p
    let SetSelectedComboBoxItem(comboBox : AutomationElement, item : string) =
        let automationPatternFromElement : AutomationPattern = GetSpecifiedPattern(comboBox, "ExpandCollapsePatternIdentifiers.Pattern")
        let expandCollapsePattern : ExpandCollapsePattern = comboBox.GetCurrentPattern(automationPatternFromElement) :?> ExpandCollapsePattern
        expandCollapsePattern.Expand()
        expandCollapsePattern.Collapse()
        let listItem : AutomationElement = comboBox.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, item))         
        automationPatternFromElement = GetSpecifiedPattern(listItem, "SelectionItemPatternIdentifiers.Pattern")
        let selectionItemPattern : SelectionItemPattern = listItem.GetCurrentPattern(automationPatternFromElement) :?> SelectionItemPattern
        selectionItemPattern.Select()
    let process = Process.Start("..\\..\\..\\FinancialReportWPF\\bin\\Release\\FinancialReportWPF.exe")
    let processId = process.Id;
    let Desktop : AutomationElement = AutomationElement.RootElement
    if Desktop = null then
        Console.WriteLine("Unable to get Desktop")
    else
        Console.WriteLine("Found Desktop\n")
       
    let mutable numWaits = 0;
    let mutable LoginWin : AutomationElement = null
    while LoginWin = null && numWaits < 50 do 
        Console.WriteLine("Looking for Login window. . . ")
        LoginWin <- Desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Test Financial Reporting"));
        numWaits <- numWaits + 1
        Thread.Sleep(200)
    if LoginWin = null then
        Console.WriteLine("Failed to find Login window")
    else
        Console.WriteLine("Found Login window")
        
    let LoginNameComboBox : AutomationElement = LoginWin.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "cboUserID"));
    if LoginNameComboBox = null then
        Console.WriteLine("No LoginNameComboBox")
    else
        Console.WriteLine("Got LoginNameComboBox")
    SetSelectedComboBoxItem(LoginNameComboBox, "MASTER")

    Tuesday, April 03, 2012 6:30 AM
  • Well, from your listing it seems that your 'LoginNameComboBox' is null. Do you have any output in Console window?

    Petr

    Wednesday, April 04, 2012 12:42 PM
  • Console said got all the controls

    AutomationElement.NameProperty <- error said this is null result in element  null in the following function

    let GetSpecifiedPattern(element : AutomationElement, patternName : string) : AutomationPattern =

    // Learn more about F# at http://fsharp.net
    open System.Windows.Automation
    open System.Diagnostics
    open System.Threading
    open System
    (*    
    let FindWindowByProcessId(processId : int) : AutomationElement =
        let targetWindow : AutomationElement= null
        let mutable count = 0;
        let p : Process = Process.GetProcessById(processId);
        let targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
        targetWindow
    //let FindElementById(processId : int, automationId : string) : AutomationElement =
        //let aeForm : AutomationElement = FindWindowByProcessId(processId)
    let FindElementById(processId : AutomationElement, automationId : string) : AutomationElement =
        let aeForm : AutomationElement = processId
        let tarFindElement : AutomationElement = aeForm.FindFirst(TreeScope.Descendants,
        new PropertyCondition(AutomationElement.AutomationIdProperty, automationId))
        tarFindElement
    let GetSelectionItemPattern(element : AutomationElement) : SelectionItemPattern =
        let mutable currentPattern : obj = null
        //p./ProgrammaticName <- "MASTER"
        if element.TryGetCurrentPattern(SelectionItemPattern.Pattern, &currentPattern) = false then
            Console.WriteLine("Element with AutomationId '{0}' and Name '{1}' does not support the SelectionItemPattern.",
                element.Current.AutomationId, element.Current.Name);
        currentPattern :?> SelectionItemPattern
    *)
    let GetSpecifiedPattern(element : AutomationElement, patternName : string) : AutomationPattern =
        let supportedPattern = element.GetSupportedPatterns()
        let mutable p : AutomationPattern = null
        for pattern in supportedPattern do
            if pattern.ProgrammaticName = patternName then
                p <- pattern
        p
    let SetSelectedComboBoxItem(comboBox : AutomationElement, item : string) =
        let automationPatternFromElement : AutomationPattern = GetSpecifiedPattern(comboBox, "ExpandCollapsePatternIdentifiers.Pattern")
        let expandCollapsePattern : ExpandCollapsePattern = comboBox.GetCurrentPattern(automationPatternFromElement) :?> ExpandCollapsePattern
        expandCollapsePattern.Expand()
        expandCollapsePattern.Collapse()
        let listItem : AutomationElement = comboBox.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, item))         
        automationPatternFromElement = GetSpecifiedPattern(listItem, "SelectionItemPatternIdentifiers.Pattern")
        let selectionItemPattern : SelectionItemPattern = listItem.GetCurrentPattern(automationPatternFromElement) :?> SelectionItemPattern
        selectionItemPattern.Select()
    let process = Process.Start("..\\..\\..\\FinancialReportWPF\\bin\\Release\\FinancialReportWPF.exe")
    let processId = process.Id;
    let Desktop : AutomationElement = AutomationElement.RootElement
    if Desktop = null then
        Console.WriteLine("Unable to get Desktop")
    else
        Console.WriteLine("Found Desktop\n")
       
    let mutable numWaits = 0;
    let mutable LoginWin : AutomationElement = null
    while LoginWin = null && numWaits < 50 do 
        Console.WriteLine("Looking for Login window. . . ")
        LoginWin <- Desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Test Financial Reporting"));
        numWaits <- numWaits + 1
        Thread.Sleep(200)
    if LoginWin = null then
        Console.WriteLine("Failed to find Login window")
    else
        Console.WriteLine("Found Login window")
        
    let mutable LoginButton = LoginWin.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Login"))
    if  LoginButton = null then
        Console.WriteLine("No LoginButton");
    else
        Console.WriteLine("Got LoginButton");
        
    let mutable QuitButton = LoginWin.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Quit"))
    if  QuitButton = null then
        Console.WriteLine("No QuitButton");
    else
        Console.WriteLine("Got QuitButton");
        
    let LoginNameComboBox : AutomationElement = LoginWin.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "cboUserID"));
    if LoginNameComboBox = null then
        Console.WriteLine("No LoginNameComboBox")
    else
        Console.WriteLine("Got LoginNameComboBox")
        
    let PasswordTextBox : AutomationElement = LoginWin.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "txtPassword"));
    if PasswordTextBox = null then
        Console.WriteLine("No txtPassword")
    else
        Console.WriteLine("Got txtPassword")
    let vpLoginTextBox : ValuePattern = PasswordTextBox.GetCurrentPattern(ValuePattern.Pattern) :?> ValuePattern
    vpLoginTextBox.SetValue("testtest")
    //let element : AutomationElement = FindElementById(processId, "cboUserID")
    SetSelectedComboBoxItem(LoginNameComboBox, "MASTER")
    //let element : AutomationElement = FindElementById(LoginNameComboBox, "5")
    //let selectionItemPattern : SelectionItemPattern = GetSelectionItemPattern(element)
    //selectionItemPattern.Select()
    //selectionItemPattern.Select()
    (*
    // Set up the CacheRequest.
    let comboCacheRequest = new CacheRequest()
    comboCacheRequest.Add(SelectionPattern.Pattern)
    comboCacheRequest.Add(SelectionPattern.SelectionProperty)
    comboCacheRequest.Add(AutomationElement.NameProperty)
    comboCacheRequest.TreeScope <- TreeScope.Element // TreeScope.Descendants;
    // Activate the CacheRequest and get the element.
    //use comboCacheRequest.Activate()
    // Load the combo box element and cache the specified properties and patterns.
    let propCondition : PropertyCondition = new PropertyCondition(AutomationElement.AutomationIdProperty, "cboUserID", PropertyConditionFlags.IgnoreCase)
    let mutable elementCombo = LoginWin.FindFirst(TreeScope.Descendants, propCondition);
    let propCondition1 : PropertyCondition = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.List)
    let listElement : AutomationElement = elementCombo.FindFirst(TreeScope.Children, propCondition1);
    *)
    // Register for ElementSelectedEvent on list items.
    (*
    if listElement <> null then
        Automation.AddAutomationEventHandler(SelectionItemPattern.ElementSelectedEvent, listElement,
            TreeScope.Children, selectHandler = new AutomationEventHandler(OnListItemSelect))
    else7
        Console.WriteLine("No listElement")
    *)
    //let pattern : SelectionPattern = LoginNameComboBox.GetCachedPattern(SelectionPattern.Pattern) :?> SelectionPattern
    //let selectedItems = pattern.Cached.GetSelection();
    //let selectedItem = selectedItems.[1]
    //let ipClickLoginButton : InvokePattern =(InvokePattern)LoginButton.GetCurrentPattern(InvokePattern.Pattern);
    //ipClickLoginButton.Invoke();
    //Thread.Sleep(1500)
    (*
    let ipClickQuitButton : InvokePattern = QuitButton.GetCurrentPattern(InvokePattern.Pattern) :?> InvokePattern
    ipClickQuitButton.Invoke();
    Thread.Sleep(1500)
    *)
    Console.ReadKey()

    Thursday, April 05, 2012 1:07 AM