J'écris une application de la barre d'état système qui doit vérifier si une application Web interne est ouverte.
Je peux vérifier IE en utilisant les éléments suivants:
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 procéder comme indiqué ci-dessus (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.)
C'est spécifique pour chaque navigateur. C'est pour les plus importants:
GetWindowText
EDIT: Depuis 2014, Chrome a changé et vous devez obtenir l'URL avec l'acessibilité.
Code pour obtenir l'URL de Firefox/Opera en utilisant DDE (qui utilisait 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;
}
}
Utilisation de UIAutomation - Obtenir les 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 liste. Mais je pense que ce n'est pas pour Chrome non?
(Vous devez ajouter NDde.dll à votre projet. Pour ce faire, accédez à la solution Explorateur, cliquez avec le bouton droit de la souris sur Références-> ajouter une référence-> Parcourir-> recherchez que DLL ( http://ndde.codeplex.com/ du 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 plutôt bien avec Chrome Version 58.0.3029.110:
Veuillez ajouter les références de UIAutomationClient et UIAutomationProvider de Assembly fournies 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);
}