YasserKhalil
YasserKhalil

Reputation: 9568

Identify element in UI Automation in VBA

I am trying to learn something new in VBA and now I am working on UI Automation. There is a browser that I am trying to interact with in specific way and everything is OK till I encountered an element with no AutomationID nor ClassName nor Name How can identify that element?

The snapshot is taken from "Accessibility Insights For Windows" tool

Here's the code I used till now

Rem References: UIAutomationClient
Rem ------------------------------
Dim MyElement As UIAutomationClient.IUIAutomationElement
Dim MyElement1 As UIAutomationClient.IUIAutomationElement

'Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public Enum oConditions
eUIA_NamePropertyId
eUIA_AutomationIdPropertyId
eUIA_ClassNamePropertyId
eUIA_LocalizedControlTypePropertyId
End Enum

Sub myDemo()
Dim AppObj As UIAutomationClient.IUIAutomationElement
Dim oInvokePattern As UIAutomationClient.IUIAutomationInvokePattern
Dim oAutomation As New CUIAutomation ' the UI Automation API\
Dim oPattern As UIAutomationClient.IUIAutomationLegacyIAccessiblePattern

Set AppObj = WalkEnabledElements("Y_browser")

Set MyElement = AppObj.FindFirst(TreeScope_Children, PropCondition(oAutomation, eUIA_AutomationIdPropertyId, "1"))
Set MyElement1 = MyElement.FindFirst(TreeScope_Children, PropCondition(oAutomation, eUIA_ClassNamePropertyId, "Edit"))
Set oPattern = MyElement1.GetCurrentPattern(UIA_LegacyIAccessiblePatternId)
oPattern.SetValue ("http://student.moe.gov.eg/new/serch_students.aspx")
Set MyElement = AppObj.FindFirst(TreeScope_Children, PropCondition(oAutomation, eUIA_NamePropertyId, "GO"))
Set oInvokePattern = MyElement.GetCurrentPattern(UIAutomationClient.UIA_InvokePatternId)
oInvokePattern.Invoke

Set MyElement1 = AppObj.FindFirst(TreeScope_Children, PropCondition(oAutomation, eUIA_ClassNamePropertyId, "Shell Embedding"))
Set MyElement = MyElement1.FindFirst(TreeScope_Children, PropCondition(oAutomation, eUIA_ClassNamePropertyId, "Shell DocObject View"))
Set MyElement1 = MyElement.FindFirst(TreeScope_Children, PropCondition(oAutomation, eUIA_ClassNamePropertyId, "Internet Explorer_Server"))
Set MyElement = MyElement1.FindFirst(TreeScope_Children, PropCondition(oAutomation, eUIA_NamePropertyId, "الادارة الالكترونية للتعليم ...بيانات التلميذ"))
Set MyElement1 = MyElement.FindFirst(TreeScope_Children, PropCondition(oAutomation, eUIA_AutomationIdPropertyId, "100"))

Rem Here's where I am stuck at ....
Set MyElement = MyElement1.FindFirst(TreeScope_Children, PropCondition(oAutomation, eUIA_LocalizedControlTypePropertyId, "item"))

Stop

End Sub


Function PropCondition(UiAutomation As CUIAutomation, Prop As oConditions, Requirement As String) As UIAutomationClient.IUIAutomationCondition
Select Case Prop
    Case 0
        Set PropCondition = UiAutomation.CreatePropertyCondition(UIAutomationClient.UIA_NamePropertyId, Requirement)
    Case 1
        Set PropCondition = UiAutomation.CreatePropertyCondition(UIAutomationClient.UIA_AutomationIdPropertyId, Requirement)
    Case 2
        Set PropCondition = UiAutomation.CreatePropertyCondition(UIAutomationClient.UIA_ClassNamePropertyId, Requirement)
    Case 3
        Set PropCondition = UiAutomation.CreatePropertyCondition(UIAutomationClient.UIA_LocalizedControlTypePropertyId, Requirement)
End Select
End Function

Function WalkEnabledElements(strWindowName As String) As UIAutomationClient.IUIAutomationElement
Dim oAutomation As New CUIAutomation
Dim condition1 As UIAutomationClient.IUIAutomationCondition
Dim condition2 As UIAutomationClient.IUIAutomationCondition
Dim walker As UIAutomationClient.IUIAutomationTreeWalker
Dim element As UIAutomationClient.IUIAutomationElement

Set walker = oAutomation.ControlViewWalker
Set element = walker.GetFirstChildElement(oAutomation.GetRootElement)

Do While Not element Is Nothing
    Rem Debug.Print element.CurrentName
    If InStr(1, element.CurrentName, strWindowName) > 0 Then
        Set WalkEnabledElements = element
        Exit Function
    End If

    Set element = walker.GetNextSiblingElement(element)
Loop
End Function

Function GetElement(elementalist As UIAutomationClient.IUIAutomationElement)
On Error Resume Next
Dim oAutomation As New CUIAutomation
Dim walker As UIAutomationClient.IUIAutomationTreeWalker

Set walker = oAutomation.ControlViewWalker
Dim element1 As UIAutomationClient.IUIAutomationElementArray
Dim element2 As UIAutomationClient.IUIAutomationElement

Dim childtree As UIAutomationClient.TreeScope
Debug.Print elementalist.CurrentName
Dim condition1 As UIAutomationClient.IUIAutomationCondition
Set condition1 = oAutomation.CreateTrueCondition
Set element1 = elementalist.FindAll(TreeScope_Children, condition1)
DoEvents
If element1.Length <> 0 Then
    Set element2 = elementalist.FindFirst(TreeScope_Children, condition1)
End If

Do While Not element2 Is Nothing
    Dim oPattern As UIAutomationClient.IUIAutomationLegacyIAccessiblePattern
    Set oPattern = element2.GetCurrentPattern(UIA_LegacyIAccessiblePatternId)

    Debug.Print element2.CurrentName & "|" & oPattern.CurrentValue

    If oPattern.CurrentName = "Notification" Then
        Set MyElement = element2
        Exit Function
    End If

    Debug.Print element2.CurrentClassName

    Debug.Print element2.CurrentAutomationId

    GetElement element2
    Debug.Print element2.CurrentName
    If Not MyElement Is Nothing Then Exit Function
    Set element2 = walker.GetNextSiblingElement(element2)
Loop

End Function

Function GetElement1(elementalist As UIAutomationClient.IUIAutomationElement)
On Error Resume Next
Dim oAutomation As New CUIAutomation
Dim walker As UIAutomationClient.IUIAutomationTreeWalker

Set walker = oAutomation.ControlViewWalker
Dim element1 As UIAutomationClient.IUIAutomationElementArray
Dim element2 As UIAutomationClient.IUIAutomationElement

Dim childtree As UIAutomationClient.TreeScope
Debug.Print elementalist.CurrentName
Dim condition1 As UIAutomationClient.IUIAutomationCondition
Set condition1 = oAutomation.CreateTrueCondition
Set element1 = elementalist.FindAll(TreeScope_Children, condition1)
DoEvents
If element1.Length <> 0 Then
    Set element2 = elementalist.FindFirst(TreeScope_Children, condition1)
End If

Do While Not element2 Is Nothing
    Dim oPattern As UIAutomationClient.IUIAutomationLegacyIAccessiblePattern
    Set oPattern = element2.GetCurrentPattern(UIA_LegacyIAccessiblePatternId)

    Debug.Print element2.CurrentName & "|" & oPattern.CurrentValue

    If element2.CurrentName = "Save" Then
        Set MyElement = element2
        Exit Function
    End If

    Debug.Print element2.CurrentClassName

    Debug.Print element2.CurrentAutomationId

    GetElement element2
    Debug.Print element2.CurrentName
    If Not MyElement Is Nothing Then Exit Function
    Set element2 = walker.GetNextSiblingElement(element2)
Loop
End Function

Function AddReference() As Boolean
Dim VBAEditor As VBIDE.VBE
Dim vbProj As VBIDE.VBProject
Dim chkRef As VBIDE.Reference
Set VBAEditor = Application.VBE
Set vbProj = ThisWorkbook.VBProject

For Each chkRef In vbProj.References
    If chkRef.Name Like "*IBM PCOMM 4.01*" Then
        GoTo Flush
    End If
Next
On Error GoTo Hell:
vbProj.References.AddFromFile Environ("systemroot") & "\system32\uiautomationcore.dll"

Hell:
If Err.Number = 48 Then
    AddReference = False
ElseIf Err.Number = 0 Then
    AddReference = True
End If
Flush:
Set vbProj = Nothing
Set VBAEditor = Nothing
End Function

And this is a link to the browser I am working on https://drive.google.com/open?id=1tDGa2iiMpEBbFVc-jMHdMB2nA1lgVFac

Upvotes: 3

Views: 3816

Answers (1)

DecimalTurn
DecimalTurn

Reputation: 4129

If the element has no Name, AutomationID nor ClassName property, you can have a look at other properties. Here is a list of the UIA properties that you have access to.

Seems like you could use the UIA_ControlTypePropertyId in this case.

Upvotes: 1

Related Questions