Get List of Open Chrome Tabs .NET
Overview
Before Google Chrome version 32, obtaining a list of open tab titles was somewhat trivial. Each tab was it’s own “Window” and had it’s own handle. So you could use that handle and obtain the title via the window caption. When Google Chrome updated to version 32, a lot happened behind the scenes with regards to UI rendering. (see here for more details).
With the v32 update, using the method mentioned above you can only obtain the current open tabs title. No good. If we want a list of all open tabs, we have to do something different. In this case, it’s using the somewhat recent UI Automation accessibility framework. This framework allows you to treewalk through an applications UI, find and interact with majority of it’s interface elements.
Finding the tabs
To browse and treewalk through UI elements of an application, you can use the inspect tool by Mirosoft found in the Windows Developer Kit. As you can see from the screenshot below, the main caption of our parent “Google Chrome Window” is the active tab title.
The Code
To get list of open Chrome Tabs and to utilise UI Automation you’ll need to add a couple of references to your project;
UIAutomationClient.dll
UIAutomationTypes.dll
Located in; C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0 (or 3.5)
VB.NET
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
'//Grab all the Chrome processes Dim chrome() As Process = Process.GetProcessesByName("chrome") '//Exit if chrome isn't running If chrome.Length <= 0 Then Exit Sub For Each chromeProcess As Process In chrome '//If the chrome process doesn't have a window handle then ignore it If chromeProcess.MainWindowHandle <> IntPtr.Zero Then '//To find the tabs we first need to locate something reliable - the 'New Tab' button Dim rootElement As AutomationElement = AutomationElement.FromHandle(chromeProcess.MainWindowHandle) Dim condNewTab As Condition = New PropertyCondition(AutomationElement.NameProperty, "New Tab") Dim elemNewTab As AutomationElement = rootElement.FindFirst(TreeScope.Descendants, condNewTab) '//Get the tabstrip by getting the parent of the 'new tab' button Dim tWalker As TreeWalker = TreeWalker.ControlViewWalker Dim elemTabStrip As AutomationElement = tWalker.GetParent(elemNewTab) '//Loop through all the tabs and get the names which is the page title Dim tabItemCondition As Condition = New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.TabItem) For Each tabItem As AutomationElement In elemTabStrip.FindAll(TreeScope.Children, tabItemCondition) Debug.WriteLine(tabItem.Current.Name) Next End If Next |
C# (Thanks to Steve Greene in comments)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
Process[] procsChrome = Process.GetProcessesByName("chrome"); if (procsChrome.Length <= 0) { Console.WriteLine("Chrome is not running"); return 0; } foreach(Process proc in procsChrome) { // the chrome process must have a window if (proc.MainWindowHandle == IntPtr.Zero) { continue; } // to find the tabs we first need to locate something reliable - the 'New Tab' button AutomationElement root = AutomationElement.FromHandle(proc.MainWindowHandle); Condition condNewTab = new PropertyCondition(AutomationElement.NameProperty, "New Tab"); AutomationElement elmNewTab = root.FindFirst(TreeScope.Descendants, condNewTab); // get the tabstrip by getting the parent of the 'new tab' button TreeWalker treewalker = TreeWalker.ControlViewWalker; AutomationElement elmTabStrip = treewalker.GetParent(elmNewTab); // loop through all the tabs and get the names which is the page title Condition condTabItem = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.TabItem); foreach(AutomationElement tabitem in elmTabStrip.FindAll(TreeScope.Children, condTabItem)) { Console.WriteLine(tabitem.Current.Name); } } |
Example Project / Github Repo
The code snippet above has one downfall, it only seems to grab a single Chrome window’s tabs. So if you have multiple Chrome windows open, it’ll just grab the last active set of tabs. I’ve uploaded a project to Github that fixes this issue and gets all open Chrome windows tab titles. Github Repo.
Conclusion
UI Automation is pretty neat. Getting the UI element title or caption is only just scratching the surface. For example it’s possible to interact with the elements such as click on buttons, set values and much more. I’ve worked quite a bit with windows and manipulating them via their handles, but being able to drill down deeper to individual UI elements will definitely come in handy.