Search code examples
.netvb.netfirefoxui-automationmicrosoft-ui-automation

Get all Firefox open Urls using Microsoft UI Automation


I'm trying to retrieve all the urls that are open in the Firefox tabs.

This is what I've done so far, the code gets all the Firefox urls, yes, but it also retrieves all the urls from each open document, for example embedded youtube urls from forums, etc... things that I'm not interested.

How I can fix that?.

And also it throws an exception

A first chance exception of type 'System.InvalidOperationException' occurred in Microsoft.VisualBasic.dll

when trying to cast as String here:

test.Add(TryCast(DirectCast(d.GetCurrentPattern(ValuePattern.Pattern), ValuePattern).Current.Value, String))

...but I suppose that problem should be solved if I can "filter" properly the controls to retrieve the proper urls.

Also another problem of this code, the UI Automation makes my Firefox process unminizable from Taskbar, I can't press the Firefox taskbar button to maximize/minimize the window after running these UI Automation instructions.

Imports System.Windows.Automation

Public Shared Function GetFirefoxUrls(process As Process) As List(Of String)

    If process Is Nothing Then
        Throw New ArgumentNullException("process")

    ElseIf process.MainWindowHandle = IntPtr.Zero Then
        Throw New ArgumentException("Invalid process.", "process")

    Else

        Dim element As AutomationElement =
            AutomationElement.FromHandle(process.MainWindowHandle)

        If element Is Nothing Then
            Return Nothing

        Else

            Dim docs As AutomationElementCollection =
                element.FindAll(TreeScope.Subtree,
                                New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document))

            If docs Is Nothing Then
                Return Nothing

            Else

                Dim test As New List(Of String)

                For Each d In docs
                    Try
                        test.Add(TryCast(DirectCast(d.GetCurrentPattern(ValuePattern.Pattern), ValuePattern).Current.Value, String))

                    Catch ex As Exception
                        Debug.WriteLine(ex.Message)
                    End Try
                Next

                Return test

            End If ' doc Is Nothing

        End If ' element Is Nothing

    End If ' process Is Nothing

End Function

Usage:

Dim urls As List(Of String) =
    GetFirefoxUrls(Process.GetProcessesByName("Firefox").First)

Solution

  • Using the Inspect tool (it's in the Windows 7 SDK), I see that all of the Firefox tabs' URL EditControls have the Name="Search or enter address". I don't recall that you can create a PropertyCondition based on the element's Name (I don't believe you can). But as you iterate over the Document elements, could you get the Name property of each and compare against "Search or enter address" before you add them to your list? --i.e., right before this line of code:

    test.Add(TryCast(DirectCast(d.GetCurrentPattern(ValuePattern.Pattern), ValuePattern).Current.Value, String))
    

    [EDIT] Oops please disregard, spoke too soon. The Name="Search or enter address" EditControl is just a control within the Navigation Toolbar parent...it's contains the current tab's URL, not the URL of each page.

    Plan B: Can you build a test app which iterates over the entire document and compares ValueProperty values agains known URL text fragments fragments in your Firefox test session--strings like "http://"? Then see what attributes those elements have in common with other URL-containing elements--maybe a common parent name, etc.