2011-10-18 160 views
21

我在寫一個系統托盤應用程序,需要檢查一個內部的基於web的應用程序是否打開。如何從Chrome和Firefox獲取開放網頁的網址?

我可以使用下面的檢查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,我該如何做與上述相同的操作(即獲取瀏覽器中任何打開的標籤的URL)? (我不打擾其他瀏覽器,因爲這些是我們組織中唯一使用的瀏覽器。)

+0

有趣的問題。我用Firefox(當前標籤)找到了一個關於[使用AutoHotkey實現它](http://www.autohotkey.com/forum/topic51981.html)的主題,那裏的討論可能會幫助你。您可以創建Firefox插件來遍歷所有選項卡,並且類似地使用Chrome。[This](http://www.autohotkey.com/forum/topic46974.html)也可能有用。 –

+0

更多鏈接:[MozRepl @ AMO](https://addons.mozilla.org/pl/firefox/addon/mozrepl/),[YouTube視頻](http://www.youtube.com/watch?v=5RSnHN6S52c )。要列出Firefox中打開的標籤的所有URL,請參閱[本擴展](https://addons.mozilla.org/en-US/firefox/addon/list-open-urls/)。 Firefox擴展基本上是包含JavaScript和XUL代碼的ZIP文件,因此您可以輕鬆定製它。 –

+1

如何檢查用戶的互聯網流量呢?例如,您可以設置[代理](http://stackoverflow.com/questions/226784/how-to-create-a-simple-proxy-in-c)。 – Dmitriy

回答

22

它對每個瀏覽器都是特定的。這對於主要的:

  • 的Internet Explorer - 您可以使用SHDOCVW(像你這樣)
  • 火狐 - 你可以使用DDE的URL(來源下同)
  • - 您可以在枚舉所有子窗口的同時獲取URL,直到獲得「Chrome_OmniboxView」類的控件,然後獲取文本使用GetWindowText
  • Opera - 您可以使用同樣的事情,火狐,但與「歌劇」
  • Safari瀏覽器 - 沒有已知的方法,因爲它使用了自定義繪製控件

編輯:從2014年,Chrome已經改變,您需要使用Acessibility獲取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」類型,並且沒有標題集。 –

+0

即使使用FireFox,即使沒有string.Split,提供的DDE代碼也只返回當前活動的選項卡。它不枚舉所有標籤。更不用說string.split是錯誤的(如果你的URL中有雙引號,它將不會返回正確的URL,例如,因爲DDE傳輸會被轉義出來)... – BrainSlugs83

+0

對於Opera,它不適用於Firefox ,我在這裏添加如何做到這一點:http://stackoverflow.com/questions/21968177/get-url-from-opera-browser – Lucian

2

也許這個代碼可以幫助的東西; 感謝BLEZ分享此代碼。我使用這段代碼從Firefox中捕獲唯一的地址並將它們添加到列表框中。但我認爲這不適合Chrome?

(你應該添加NDde.dll到您的項目,要做到這一點去Solution Explorer中右鍵點擊引用 - >添加參考 - > Browse->查找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")); 
      } 
     } 
    } 
} 
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.Children, Condition.TrueCondition)) 
         { 
          if (ii.Current.LocalizedControlType == "document") 
          { 
           if (!ii.Current.BoundingRectangle.X.ToString().Contains("Infinity")) 
           { 
            ValuePattern activeTab = ii.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern; 
            var activeUrl = activeTab.Current.Value; 
            return activeUrl; 
           } 
          } 
         } 
        } 
       } 
      } 
+0

.net framework 3.0及更高版本爲 – K3rnel31

+0

對於Chrome,新的PropertyCondition(AutomationElement.ControlTypeProperty ,ControlType.TabItem)似乎列出了所有的標籤,這些標籤是你在找到'elm1'後會感興趣的孩子。 –

+2

然而,看起來只有當前活動標籤可以用這種方法找到。:-( –

0

下面的代碼工作相當不錯的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); 
     }