Comment puis-je obtenir des URL de pages ouvertes de Chrome et Firefox?
J'écris une application de barre d'état système qui doit vérifier si une application web interne est ouverte.
Je peux vérifier IE en utilisant ce qui suit:
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);
Cependant, certains utilisateurs du système préfèrent Chrome ou Firefox.
Comment puis-je faire la même chose que ci-dessus (c'est-à-dire obtenir les URL de tous les onglets ouverts dans le navigateur) pour Chrome et Firefox? (Je ne vais pas m'embêter avec d'autres navigateurs car ce sont les seuls utilisés dans notre organisation.)
4 réponses
Il est spécifique à chaque navigateur. C'est pour les grands:
- Internet Explorer - Vous pouvez utiliser SHDocVw (comme vous l'avez fait)
- Firefox - vous pouvez obtenir L'URL en utilisant DDE (source ci-dessous)
-
Chrome - vous pouvez obtenir L'URL tout en énumérant toutes les fenêtres enfants jusqu'à ce que vous arriviez au contrôle avec la classe "Chrome_OmniboxView", puis obtenir le texte en utilisant
GetWindowText
- Opéra - Vous pouvez utiliser la même chose que Firefox, mais avec "opéra"
- Safari - Il N'y a pas de méthode connue car elle utilise des contrôles dessinés personnalisés
EDIT: depuis 2014, Chrome a changé et vous devez obtenir L'URL avec Acessibilité.
Code pour obtenir L'URL de Firefox / Opera en utilisant DDE (qui a utilisé NDDE - le seul bon wrapper DDE pour. NET):
//
// 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;
}
}
En utilisant UIAutomation-obtenir des URL pour FireFox et 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;
}
}
}
}
}
}
Peut-être que ce code peut aider quelque chose; Merci à BLEZ pour partager ce code. J'utilise ce code pour capturer des adresses uniques de firefox et les ajouter à une listbox. Mais je pense que ce N'est pas pour Chrome Non?
(vous devriez ajouter NDde.dll à votre projet, pour ce faire, allez dans l'Explorateur de solutions cliquez avec le bouton droit sur Références - > ajouter une référence - > parcourir - > trouver cette DLL ( http://ndde.codeplex.com / depuis le dossier binaire.))
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"));
}
}
}
}
Le code ci-dessous fonctionne assez bien avec la version Chrome 58.0.3029.110:
Veuillez ajouter la référence de UIAutomationClient et UIAutomationProvider à partir de L'assemblage fourni par. NET.
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);
}