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

23

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

我可以使用以下方法检查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浏览器。

我应该如何以同样的方式(即获取浏览器中任何打开标签页的URL)来处理Chrome和Firefox?(由于这两个浏览器是我们组织中唯一使用的浏览器,所以我不会去烦其他浏览器。)


有趣的问题。我找到了一个关于使用AutoHotkey(http://www.autohotkey.com/forum/topic51981.html)在Firefox(当前标签页)中实现此功能的帖子,那里的讨论可能会对您有所帮助。您可以创建Firefox插件,以便遍历所有选项卡,并类似地处理Chrome。这个(http://www.autohotkey.com/forum/topic46974.html)也可能很有用。 - jakub.g
更多链接:MozRepl @ AMOYouTube 视频。要列出 Firefox 中打开的所有选项卡的 URL,请参见此扩展程序。Firefox 扩展程序基本上是包含 JavaScript 和 XUL 代码的 ZIP 文件,因此您可以轻松自定义它。 - jakub.g
1
那么检查用户的互联网流量怎么样?例如,您可以设置一个代理。 - Dmitriy
你可以参考指南 - Chintan
4个回答

23

每个浏览器都有特定的方法。以下是主要浏览器的方法:

  • Internet Explorer - 你可以使用 SHDocVw(如你所做的那样)
  • Firefox - 你可以使用 DDE 获取 URL(下面有源代码)
  • Chrome - 你可以在枚举所有子窗口直到找到类名为“Chrome_OmniboxView”的控件,然后使用GetWindowText获取文本来获得 URL
  • Opera - 你可以使用与 Firefox 相同的方法,只需将“opera”替换为“firefox”即可
  • Safari - 还没有已知方法,因为它使用自定义绘制的控件

编辑:自2014年以来,Chrome 已经更改,需要使用 Accessibility 获取 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;
    }
}

1
对于 Chrome 浏览器,这可能在后续版本中发生了变化?Chrome_WidgitWin_1 的所有子窗口都是 Static 类型,并且没有设置标题。 - Steven Jeuris
即使使用FireFox,即使没有使用string.Split,提供的DDE代码仅返回当前活动选项卡。它不会枚举所有选项卡。更不用说string.split存在缺陷(例如,如果您的URL中有双引号,则它将无法返回正确的URL,因为它变成了DDE传输的转义字符)... - BrainSlugs83
对于 Opera 浏览器,它并不像 Firefox 一样工作。我在这里添加了如何实现的方法:http://stackoverflow.com/questions/21968177/get-url-from-opera-browser - Lucian
2
自从49版本以后,Firefox的DDE方法已经停止工作 :( - Jon Limjap
@ Ayorus,你可以使用无障碍功能在Firefox中获取URL。例如,在Firefox Quantum中,地址栏的名称为“使用{搜索引擎}搜索或输入地址”,其中{搜索引擎}可能是Google、Bing或任何其他搜索引擎。您可以检查您正在搜索的字段的名称是否以“使用”开头,并以“或输入地址”结尾。请注意,这种方法仅适用于英文版本。在其他语言中,此字段的名称可能不同。 - SyndicatorBBB
显示剩余2条评论

6

使用UIAutomation - 获取FireFox和Chrome的URL:

 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 后您感兴趣的子元素。 - Steven Jeuris
3
然而,似乎只有当前活动的选项卡可以使用这种方法被找到。 :-( - Steven Jeuris

2
也许这段代码可以帮到你;感谢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"));
            }
        }
    }
}

0
以下代码在 Chrome 版本 58.0.3029.110 中运行良好:
请从 .NET 提供的程序集中添加 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);
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接