C# How to get tabs from chrome in multiple windows?

此生再无相见时 提交于 2020-05-13 17:39:48

问题


So I have code that extracts all the tabs from a window of chrome.

However if I there are multiple windows open, only the most recent one is recognised.

Is it possible to extract the tabs from multiple windows instead of only the most recent one?

EDIT: The code that I use and needs fixing:

public List<string> ChromeTabs()
    {
        List<string> ret = new List<string>();

        Process[] procsChrome = Process.GetProcessesByName("chrome");

        if (procsChrome.Length <= 0)
        {
            Console.WriteLine("Chrome is not running");
        }
        else
        {
            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); // <- Error on this line

                // 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))
                {
                    ret.Add(tabitem.Current.Name);
                    //Console.WriteLine(tabitem.Current.Name);
                }
                continue;
            }
        }
        return ret;
    }`

回答1:


I was also running into this issue where only the most recent used Google Chrome window was returning a non-zero MainWindowHandle which was in turn preventing me from getting tab information from other Google Chrome windows.

I ended up fixing this by enumerating through the desktop windows and finding the Handle of each Google Chrome process that adhered to a set of rules that I found (through hours of debugging) that reliably returns browser windows.

I was able to pass the Handles found during desktop window enumeration to the typical AutomationElement method used to get the tab information of all running Google Chrome windows.

delegate bool EnumWindowsProc(IntPtr hWnd, int lParam);

[DllImport("user32.dll")]
private static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumWindowsProc ewp, int lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern bool GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

[DllImport("user32.dll")]
private static extern uint GetWindowText(IntPtr hWnd, StringBuilder lpString, uint nMaxCount);

[DllImport("user32.dll")]
private static extern uint GetWindowTextLength(IntPtr hWnd);

[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

// get all the process id's of the running chrome processes
Process[] chromeProcesses = Process.GetProcessesByName("chrome");
List<uint> chromeProcessIds = chromeProcesses.Select(x => (unit)x.Id).ToList();

// a list to store the handles of the Google Chrome windows that we'll find
List<IntPtr> windowHandles = new List<IntPtr>();

EnumWindowsProc enumerateHandle = delegate (IntPtr hWnd, int lParam)
{
    // get the id of the process of the window we are enumerating over
    uint id;
    GetWindowThreadProcessId(hWnd, out id);

    // if the process we're enumerating over has an id in our chrome process ids, we need to inspect it to see if it is a window or other process
    if (chromeProcessIds.Contains(id))
    {
        // get the name of the class of the window we are inspecting
        var clsName = new StringBuilder(256);
        var hasClass = GetClassName(hWnd, clsName, 256);
        if (hasClass)
        {
            // get the text of the window we are inspecting
            var maxLength = (int)GetWindowTextLength(hWnd);
            var builder = new StringBuilder(maxLength + 1);
            GetWindowText(hWnd, builder, (uint)builder.Capacity);

            var text = builder.ToString();
            var className = clsName.ToString();

            // actual Google Chrome windows have text set to the title of the active tab
            // in my testing, this needs to be coupled with the class name equaling "Chrome_WidgetWin_1". 
            // i haven't tested this with other versions of Google Chrome
            if (!string.IsNullOrWhiteSpace(text) && className.Equals("Chrome_WidgetWin_1", StringComparison.OrdinalIgnoreCase))
            {
                // if we satisfy the conditions, this is a Google Chrome window. Add the handle to the list of handles to use later.
                windowHandles.Add(hWnd);
            }
        }
    }
    return true;
};

EnumDesktopWindows(IntPtr.Zero, enumerateHandle, 0);

foreach (IntPtr ptr in windowHandles)
{
    AutomationElement root = AutomationElement.FromHandle(ptr);

    // continue grabbing Chrome tab information using the AutomationElement method
    ...
}


来源:https://stackoverflow.com/questions/44602890/c-sharp-how-to-get-tabs-from-chrome-in-multiple-windows

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!