Reputation: 9568
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
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