如何从 Chrome 和 Firefox 获取打开页面的 URL?

Posted

技术标签:

【中文标题】如何从 Chrome 和 Firefox 获取打开页面的 URL?【英文标题】:How can I get URLs of open pages from Chrome and Firefox? 【发布时间】:2011-12-10 11:19:06 【问题描述】:

我正在编写一个系统托盘应用程序,它需要检查基于网络的内部应用程序是否打开。

我可以使用以下方法检查 IE:

SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindows();
        string filename;
        bool sdOpen = false;
        foreach (SHDocVw.InternetExplorer ie in shellWindows)
        
            filename = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
            if (filename.Equals("iexplore"))
            
                string[] urlParts = (ie.LocationURL.ToString()).Split('/');
                string website = urlParts[2];
                if (website == "myApp:8080")  sdOpen = true; ;
            
        

        if (sdOpen)  Console.WriteLine("App is open");  else  Console.WriteLine("App is not open"); ;

        Console.ReadKey(true);

但是,一些使用该系统的用户更喜欢 Chrome 或 Firefox。

如何为 Chrome 和 Firefox 执行上述操作(即获取浏览器中任何打开的标签页的网址)? (我不会打扰其他浏览器,因为这些是我们组织中唯一使用的浏览器。)

【问题讨论】:

有趣的问题。我找到了一个关于doing it with AutoHotkey with Firefox (current tab) 的线程,那里的讨论可能会对你有所帮助。您可以创建 Firefox 插件来遍历所有选项卡,与 Chrome 类似。 This 也可能有用。 更多链接:MozRepl @ AMO、YouTube video。要列出 Firefox 中打开的选项卡的所有 URL,请参阅 this extension。 Firefox 扩展基本上是包含 javascript 和 XUL 代码的 ZIP 文件,因此您可以轻松自定义它。 检查用户的互联网流量怎么样?例如,您可以设置proxy。 可以参考Guideline 【参考方案1】:

它特定于每个浏览器。这是主要的:

Internet Explorer - 您可以使用 SHDocVw(就像您一样) Firefox - 您可以使用 DDE 获取 URL(来源如下) Chrome - 您可以在枚举所有子窗口时获取 URL,直到您使用“Chrome_OmniboxView”类访问控件,然后使用 GetWindowText 获取文本 Opera - 您可以使用与 Firefox 相同的功能,但使用“opera” Safari - 没有已知方法,因为它使用自定义绘制的控件

编辑:自 2014 年以来,Chrome 发生了变化,您需要获取具有可访问性的 URL。

使用 DDE 从 Firefox/Opera 获取 URL 的代码(使用 NDDE - .NET 的唯一良好 DDE 包装器):

//
// usage: GetBrowserURL("opera") or GetBrowserURL("firefox")
//

private string GetBrowserURL(string browser) 
    try 
        DdeClient dde = new DdeClient(browser, "WWW_GetWindowInfo");
        dde.Connect();
        string url = dde.Request("URL", int.MaxValue);
        string[] text = url.Split(new string[]  "\",\"" , StringSplitOptions.RemoveEmptyEntries);
        dde.Disconnect();
        return text[0].Substring(1);
     catch 
        return null;
    

【讨论】:

对于 Chrome 这可能会在以后的版本中改变? Chrome_WidgitWin_1 的所有子窗口都是 Static 类型并且没有标题集。 即使使用 FireFox,即使没有 string.Split,提供的 DDE 代码也只会返回当前活动的选项卡。它不会枚举所有选项卡。更不用说 string.split 是错误的(例如,如果您的 URL 中有双引号,它将不会返回正确的 URL,因为它会为 DDE 传输而转义)... 对于 Opera 它不像 Firefox 那样工作,我在这里添加了如何做到这一点:***.com/questions/21968177/get-url-from-opera-browser Firefox 的 DDE 方法从 49 版开始停止工作 :( 你好@JonLimjap,你找到另一种获取 URL 信息的方法了吗?【参考方案2】:

使用 UIAutomation - 获取 FireFox 和 Chrome 的网址:

 else if (browser == BrowserType.Chrome)
        
            //"Chrome_WidgetWin_1"

            Process[] procsChrome = Process.GetProcessesByName("chrome");
            foreach (Process chrome in procsChrome)
            
                // the chrome process must have a window
                if (chrome.MainWindowHandle == IntPtr.Zero)
                
                    continue;
                
                //AutomationElement elm = AutomationElement.RootElement.FindFirst(TreeScope.Children,
                //         new PropertyCondition(AutomationElement.ClassNameProperty, "Chrome_WidgetWin_1"));
                // find the automation element
                AutomationElement elm = AutomationElement.FromHandle(chrome.MainWindowHandle);

                // manually walk through the tree, searching using TreeScope.Descendants is too slow (even if it's more reliable)
                AutomationElement elmUrlBar = null;
                try
                
                    // walking path found using inspect.exe (Windows SDK) for Chrome 29.0.1547.76 m (currently the latest stable)
                    var elm1 = elm.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Google Chrome"));
                    var elm2 = TreeWalker.ControlViewWalker.GetLastChild(elm1); // I don't know a Condition for this for finding :(
                    var elm3 = elm2.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, ""));
                    var elm4 = elm3.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ToolBar));
                    elmUrlBar = elm4.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Address and search bar"));
                
                catch
                
                    // Chrome has probably changed something, and above walking needs to be modified. :(
                    // put an assertion here or something to make sure you don't miss it
                    continue;
                

                // make sure it's valid
                if (elmUrlBar == null)
                
                    // it's not..
                    continue;
                

                // elmUrlBar is now the URL bar element. we have to make sure that it's out of keyboard focus if we want to get a valid URL
                if ((bool)elmUrlBar.GetCurrentPropertyValue(AutomationElement.HasKeyboardFocusProperty))
                
                    continue;
                

                // there might not be a valid pattern to use, so we have to make sure we have one
                AutomationPattern[] patterns = elmUrlBar.GetSupportedPatterns();
                if (patterns.Length == 1)
                
                    string ret = "";
                    try
                    
                        ret = ((ValuePattern)elmUrlBar.GetCurrentPattern(patterns[0])).Current.Value;
                    
                    catch  
                    if (ret != "")
                    
                        // must match a domain name (and possibly "https://" in front)
                        if (Regex.IsMatch(ret, @"^(https:\/\/)?[a-zA-Z0-9\-\.]+(\.[a-zA-Z]2,4).*$"))
                        
                            // prepend http:// to the url, because Chrome hides it if it's not SSL
                            if (!ret.StartsWith("http"))
                            
                                ret = "http://" + ret;
                            
                            return ret;
                        
                    
                    continue;
                
            

        
        else if (browser == BrowserType.Firefox)
        
            AutomationElement root = AutomationElement.RootElement.FindFirst(TreeScope.Children,
                new PropertyCondition(AutomationElement.ClassNameProperty, "MozillaWindowClass"));

                Condition toolBar = new AndCondition(
                new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ToolBar),
                new PropertyCondition(AutomationElement.NameProperty, "Browser tabs"));
                var tool = root.FindFirst(TreeScope.Children, toolBar);

                var tool2 = TreeWalker.ControlViewWalker.GetNextSibling(tool);

                var children = tool2.FindAll(TreeScope.Children, Condition.TrueCondition);

                foreach (AutomationElement item in children)
                
                    foreach (AutomationElement i in item.FindAll(TreeScope.Children, Condition.TrueCondition))
                    
                        foreach (AutomationElement ii in i.FindAll(TreeScope.Element, Condition.TrueCondition))
                        
                            if (ii.Current.LocalizedControlType == "edit")
                            
                                if (!ii.Current.BoundingRectangle.X.ToString().Contains("empty"))
                                
                                    ValuePattern activeTab = ii.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                                    var activeUrl = activeTab.Current.Value;
                                    return activeUrl;
                                
                            
                        
                    
                
            

【讨论】:

对于 Chrome,new PropertyCondition( AutomationElement.ControlTypeProperty, ControlType.TabItem ) 似乎列出了所有选项卡,这是您找到 elm1 后感兴趣的子项。 但是,使用这种方法似乎只能找到当前活动的选项卡。 :-(【参考方案3】:

也许这段代码可以有所帮助; 感谢 BLEZ 分享此代码。我使用此代码从 firefox 捕获唯一地址并将它们添加到列表框中。但我认为这不适用于 Chrome 对吧?

(您应该将 NDde.dll 添加到您的项目中,为此请转到解决方案资源管理器,右键单击“参考”-> 添加参考-> 浏览-> 找到该 DLL(来自二进制文件夹的http://ndde.codeplex.com/。))

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NDde.Client;

namespace WindowsFormsApplication9

    public partial class Form1 : Form
    
        public Form1()
        
            InitializeComponent();
        

        private void button1_Click(object sender, EventArgs e)
        
            timer1.Enabled = true;
        

        private string GetBrowserURL(string browser)
        
            try
            
                DdeClient dde = new DdeClient(browser, "WWW_GetWindowInfo");
                dde.Connect();
                string url = dde.Request("URL", int.MaxValue);
                string[] text = url.Split(new string[]  "\",\"" , StringSplitOptions.RemoveEmptyEntries);
                dde.Disconnect();
                return text[0].Substring(1);
            
            catch
            
                return null;
            
        

        private void timer1_Tick(object sender, EventArgs e)
        
            int j=0;
            for (int i = 0; i < listBox1.Items.Count; i++)
            
                if (listBox1.Items[i].ToString() == GetBrowserURL("Firefox"))
                
                    break;
                
                else
                
                    j++;
                
            
            if (j == listBox1.Items.Count)
            
                listBox1.Items.Add(GetBrowserURL("Firefox"));
            
        
    

【讨论】:

【参考方案4】:

以下代码在 Chrome 版本 58.0.3029.110 上运行良好:

请从.NET 提供的Assembly 中添加对UIAutomationClient 和UIAutomationProvider 的引用。

        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);
            var SearchBar = root.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Address and search bar"));
            if (SearchBar != null)
                return (string)SearchBar.GetCurrentPropertyValue(ValuePatternIdentifiers.ValueProperty);
        

【讨论】:

以上是关于如何从 Chrome 和 Firefox 获取打开页面的 URL?的主要内容,如果未能解决你的问题,请参考以下文章

在 Firefox/Chrome 上打开新标签页或窗口时,如何获得新的浏览器会话?

如何在 Chrome/Firefox 中打开 SharePoint 文件

Chrome 或 Firefox 中的 Web 开发人员模式:如何获取对象的 CSS 完整选择器?

Python+Selenium基础篇之3-打开和关闭IE/Chrome浏览器

保存并打开Firefox和Chrome中的标签页

如何修复firefox和chrome中的空间?