I am using following code to extract the current tab url from Google chrome, but it consumes huge CPU(10-15%) while capturing the url. Below is my code, I want to optimize the following code.
public static string GetChromeUrl(Process process)
{
try
{
if (process == null)
throw new ArgumentNullException("process");
if (process.MainWindowHandle == IntPtr.Zero)
return null;
AutomationElement element = AutomationElement.FromHandle(process.MainWindowHandle);
if (element == null)
return null;
AutomationElement edit = element.FindFirst(TreeScope.Subtree,
new AndCondition(
new PropertyCondition(AutomationElement.NameProperty, "address and search bar", PropertyConditionFlags.IgnoreCase),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit)));
if (edit != null)
{
var i = ((ValuePattern)edit.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
return i;
}
else
{
return "";
}
}
catch (Exception ex)
{
return "";
}
}
Related
From below code I can get current Chrome URL but it takes time. Sometime it takes more than 2 Min and sometime it did not return any value.
Please guide me to solve this problem.
public string GetActiveTabUrl_Google_Chrome()
{
Process[] procsChrome = Process.GetProcessesByName("chrome");
if (procsChrome.Length <= 0)
return null;
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);
}
}
}
I've googled a lot but did not get the exact solution. I've tried multiple PC but found the same problem.
Thanks
The key to reducing the time required is to use more conditions and also not to use the NameProperty, which seems to take a lot of time. Using the following code, I was able to get the URL in about 4 seconds.
static string GetURL()
{
Process[] procsChrome = Process.GetProcessesByName("chrome");
foreach (Process chrome in procsChrome)
{
if (chrome.MainWindowHandle == IntPtr.Zero)
continue;
AutomationElement root = AutomationElement.FromHandle(chrome.MainWindowHandle);
if (root == null)
return null;
Condition conditions = new AndCondition( // using multiple conditions which seems to be faster and descibe URL bar
new PropertyCondition(AutomationElement.ProcessIdProperty, chrome.Id),
new PropertyCondition(AutomationElement.IsControlElementProperty, true),
new PropertyCondition(AutomationElement.IsContentElementProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
AutomationElement urlbar = root.FindFirst(TreeScope.Descendants, conditions);
return (string)urlbar.GetCurrentPropertyValue(ValuePatternIdentifiers.ValueProperty);
}
return null;
}
Screenshot:
We are using UIAutomation to monitor the urls for browser, but what we observerd is when ever we start capturing the url the browser are using high cpu and its getting not responding. how come my application effects to browser to use high cpu. This issue is observed in all latest browser only earlier we never faced this kind of issue.
Here is code which i am using to get the url
///--------------------------------------------------------------------------------
/// <summary>
/// Get URL by using AutomatioElement.
/// </summary>
/// <param name="process"></param>
/// <param name="logPrefix"></param>
/// <returns>Url</returns>
private string GetProcessURL(Process process, string logPrefix)
{
AutomationElement UrlBarElement = null;
AutomationElement mainWindowElement = null;
AutomationElement rootElement = null;
try
{
mainWindowElement = AutomationElement.FromHandle(process.MainWindowHandle);
if (mainWindowElement == null)
{
log.Warn(logPrefix + " - Unable to capture the URL as MainWindowElement is Null.");
return null;
}
switch (process.ProcessName)
{
case ApplicationConstants.MicrosoftEdge:
rootElement = AutomationElement.FromHandle(GetDesktopWindow());
foreach (AutomationElement child in rootElement.FindAll(TreeScope.Children, PropertyCondition.TrueCondition))
{
AutomationElement window = GetEdgeCommandsWindow(child);
if (window == null) // not edge
continue;
return GetEdgeUrl(window);
}
break;
case ApplicationConstants.Opera:
UrlBarElement = mainWindowElement.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, ApplicationConstants.OperaNameProperty));
break;
case ApplicationConstants.Chrome:
Condition chromeConditions = new OrCondition(
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit),
new PropertyCondition(AutomationElement.NameProperty, ApplicationConstants.ChromeNameProperty));
UrlBarElement = mainWindowElement.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, ApplicationConstants.ChromeNameProperty));
break;
case ApplicationConstants.FireFox:
Condition fireFoxConditions = new AndCondition(
new PropertyCondition(AutomationElement.NameProperty, ApplicationConstants.FireFoxNameProperty),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
UrlBarElement = mainWindowElement.FindFirst(TreeScope.Descendants, fireFoxConditions);
if (UrlBarElement == null)
{
fireFoxConditions = new OrCondition(
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Text));
UrlBarElement = mainWindowElement.FindFirst(TreeScope.Descendants, fireFoxConditions);
}
break;
default:
UrlBarElement = mainWindowElement.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
break;
}
//Comment Before Deployment.
//Thread.Sleep(5000);
if (UrlBarElement != null)
{
return ((ValuePattern)UrlBarElement.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
else
{
log.Info(logPrefix + " - Unable to capture the URL because unable to detect the URLBarelement");
return null;
}
}
catch (Exception exx)
{
}
finally
{
mainWindowElement = null;
process = null;
UrlBarElement = null;
rootElement = null;
//GC.Collect();
}
return null;
}
I'm trying to search my inbox and all subfolders for a given string in the subject line. I found the following code online(https://www.add-in-express.com/creating-addins-blog/2012/05/31/outlook-search-csharp-vbnet/), but it returns zero results which is not the expected result.
I looked at the filter under view settings in outlook for a given search term that returns results in the outlook explorer and got this query: "http://schemas.microsoft.com/mapi/proptag/0x0037001f" LIKE '%Ticket%'
When I plug that in to the below code I likewise get zero results.
When I use LINQ to query those folders(LINQ is too slow to be a real solution here) I can get results so I'm guessing I'm making a syntactical error with advancedsearch. It is hard to find examples of usage on the web. I will appreciate anyone that can help me.
private Search RunAdvancedSearch(Outlook._Application OutlookApp, string wordInSubject)
{
string advancedSearchTag = "New Search";
string scope = "Inbox";
string filter = "\"urn:schemas:mailheader:subject\" LIKE '%"+ wordInSubject +"%'";
Outlook.Search advancedSearch = null;
Outlook.MAPIFolder folderInbox = null;
Outlook.MAPIFolder folderSentMail = null;
Outlook.NameSpace ns = null;
try
{
ns = OutlookApp.GetNamespace("MAPI");
folderInbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
folderSentMail = ns.GetDefaultFolder(
Outlook.OlDefaultFolders.olFolderSentMail);
scope = "\'" + folderInbox.FolderPath +
"\',\'" + folderSentMail.FolderPath + "\'";
advancedSearch = OutlookApp.AdvancedSearch(
scope, filter, true, advancedSearchTag);
System.Diagnostics.Debug.WriteLine(advancedSearch.Results.Count);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message, "An exception is thrown!");
}
finally
{
if (advancedSearch != null) Marshal.ReleaseComObject(advancedSearch);
if (folderSentMail != null) Marshal.ReleaseComObject(folderSentMail);
if (folderInbox != null) Marshal.ReleaseComObject(folderInbox);
if (ns != null) Marshal.ReleaseComObject(ns);
}
return advancedSearch;
}
I was not waiting long enough for the results. When AdvancedSearch(which runs in a separate thread) is finished it fires off an event called AdvancedSearchComplete. I had to tell the code to handle the event in order to wait for the search to complete.
In RunAdvancedSearch I do this in the Try with this:
Application.AdvancedSearchComplete += Application_AdvancedSearchComplete;
Here is the whole thing.
string advancedSearchTag = "MY FOOFOO Search";
//SEARCH Function
Search RunAdvancedSearch(Outlook.Application Application, string wordInSubject)
{
string scope = "Inbox";
string filter = "urn:schemas:mailheader:subject LIKE \'%" + wordInSubject + "%\'";
Outlook.Search advancedSearch = null;
Outlook.MAPIFolder folderInbox = null;
Outlook.MAPIFolder folderSentMail = null;
Outlook.NameSpace ns = null;
try
{
ns = Application.GetNamespace("MAPI");
folderInbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
folderSentMail = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail);
scope = "\'" + folderInbox.FolderPath + "\',\'" +
folderSentMail.FolderPath + "\'";
advancedSearch = Application.AdvancedSearch(
scope, filter, true, advancedSearchTag);
Application.AdvancedSearchComplete += Application_AdvancedSearchComplete;
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message, "An eexception is thrown");
}
finally
{
if (advancedSearch != null) Marshal.ReleaseComObject(advancedSearch);
if (folderSentMail != null) Marshal.ReleaseComObject(folderSentMail);
if (folderInbox != null) Marshal.ReleaseComObject(folderInbox);
if (ns != null) Marshal.ReleaseComObject(ns);
}
return advancedSearch;
}
//Handle AdvancedSearchComplete event
void Application_AdvancedSearchComplete(Outlook.Search SearchObject)
{
Outlook.Results advancedSearchResults = null;
Outlook.MailItem resultItem = null;
System.Text.StringBuilder strBuilder = null;
try
{
if (SearchObject.Tag == advancedSearchTag)
{
advancedSearchResults = SearchObject.Results;
System.Diagnostics.Debug.WriteLine("Count: " + advancedSearchResults.Count);
if (advancedSearchResults.Count > 0)
{
strBuilder = new System.Text.StringBuilder();
strBuilder.AppendLine("Number of items found: " +
advancedSearchResults.Count.ToString());
foreach (MailItem item in advancedSearchResults)
{
System.Diagnostics.Debug.WriteLine(item.Subject);
}
for (int i = 1; i <= advancedSearchResults.Count; i++)
{
resultItem = advancedSearchResults[i] as Outlook.MailItem;
if (resultItem != null)
{
strBuilder.Append("#" + i.ToString());
strBuilder.Append(" Subject: " + resultItem.Subject);
strBuilder.Append(" \t To: " + resultItem.To);
strBuilder.AppendLine(" \t Date: " +
resultItem.SentOn.ToString());
Marshal.ReleaseComObject(resultItem);
}
}
if (strBuilder.Length > 0)
System.Diagnostics.Debug.WriteLine(strBuilder.ToString());
else
System.Diagnostics.Debug.WriteLine(
"There are no Mail items found.");
}
else
{
System.Diagnostics.Debug.WriteLine("There are no items found.");
}
}
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message, "An exception is occured");
}
finally
{
if (resultItem != null) Marshal.ReleaseComObject(resultItem);
if (advancedSearchResults != null)
Marshal.ReleaseComObject(advancedSearchResults);
}
}
private void btnOutlookSrch_Click(object sender, EventArgs e)
{
Outlook.Application OLook = new Outlook.Application();
RunAdvancedSearch(OLook, "Hello?");
}
Your filter is working good, use Application:
private Search RunAdvancedSearch(Outlook.Application OutlookApp, string wordInSubject)
https://msdn.microsoft.com/en-us/library/office/microsoft.office.interop.outlook.application.aspx
Read about using _Application and Application in msdn "Remarks". There is very well written.
hi i want to get URL from browsers and for chrome i used these and the is not working getting null exception i think chrome has changed something.. getting error on elm4 == null.
using UIAutomation i searched more and all the example are not working ...
refrences:- https://stackoverflow.com/a/21799588/5096993
https://social.msdn.microsoft.com/Forums/vstudio/en-US/39bf60a8-2bdc-4aa0-96fb-08dca49cdb06/c-get-all-chrome-urls-opened?forum=csharpgeneral
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;
}
}
}
this code is working for me and get URL of active tab of chrome
Process[] procsChrome = Process.GetProcessesByName("chrome");
foreach (Process chrome in procsChrome)
{
// the chrome process must have a window
if (chrome.MainWindowHandle == IntPtr.Zero)
{
continue;
}
// find the automation element
AutomationElement elm = AutomationElement.FromHandle(chrome.MainWindowHandle);
AutomationElement elmUrlBar = elm.FindFirst(TreeScope.Descendants,
new PropertyCondition(AutomationElement.NameProperty, "Address and search bar"));
// if it can be found, get the value from the URL bar
if (elmUrlBar != null)
{
AutomationPattern[] patterns = elmUrlBar.GetSupportedPatterns();
if (patterns.Length > 0)
{
ValuePattern val = (ValuePattern)elmUrlBar.GetCurrentPattern(patterns[0]);
Console.WriteLine("Chrome URL found: " + val.Current.Value);
listbox.Items.Add(val.Current.Value);
}
}
}
I solved the same problem recently with System.Windows.Forms.SendKeys
Compared to your result - it's 4 times faster, but doesn't work with websites which use ctrl+l hotkey (for example StackOwerflow in edit mode).
Depends on your needs :)
public void WithSendkeys()
{
AutomationElement.RootElement
.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "Chrome_WidgetWin_1"))
.SetFocus();
SendKeys.SendWait("^l");
var elmUrlBar = AutomationElement.FocusedElement;
var valuePattern = (ValuePattern) elmUrlBar.GetCurrentPattern(ValuePattern.Pattern);
Console.WriteLine(valuePattern.Current.Value);
}
Here is the code:
AutomationElement root = AutomationElement.FromHandle(proc.MainWindowHandle);
Condition condNewTab = new PropertyCondition(AutomationElement.NameProperty, "Novo separador");
AutomationElement elmNewTab = root.FindFirst(TreeScope.Descendants, condNewTab);
TreeWalker treewalker = TreeWalker.ControlViewWalker;
// IF THROWS A ERROR HERE, LOOK AT THE AutomationElement.NameProperty ("Novo separador") - PUT THIS TEXT IN APROPRIATE LANGUAGE
AutomationElement elmTabStrip = treewalker.GetParent(elmNewTab);
Condition condTabItem = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.TabItem);
foreach (AutomationElement tabitem in elmTabStrip.FindAll(TreeScope.Children, condTabItem))
{
// HERE IS YOUR TABS!!!!
ret.Add(tabitem.Current.Name);
}
I'm writing a system tray app that needs to check if an internal web based app is open.
I can check IE using the following:
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);
However, some of the users using the system prefer Chrome or Firefox.
How can I do the same as above (i.e. get the urls of any open tabs in the browser) for Chrome and Firefox? (I'm not going to bother with other browsers as these are the only ones in use in our organisation.)
It's specific for every browser. That's for the major ones:
Internet Explorer - You can use SHDocVw (like you did)
Firefox - You can get the URL using DDE (source below)
Chrome - You can get the URL while enumerating all the child windows untill you get to the control with class "Chrome_OmniboxView" and then get the text using GetWindowText
Opera - You can use the same thing as Firefox, but with "opera"
Safari - There is no known method since it uses custom drawn controls
EDIT: Since 2014, Chrome has changed and you need to get the URL with Acessibility.
Code to get the URL from Firefox/Opera using DDE (which used NDDE - the only good DDE wrapper for .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;
}
}
Using UIAutomation - get urls for FireFox and 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;
}
}
}
}
}
}
Maybe this code can help something;
Thanks to BLEZ for share this code. I use this code to capture unique addresses from firefox and add them to a listbox. But I think this is not for Chrome right?
(you Should add NDde.dll to your project, to do this go to solution explorer right click to References-> add Reference->Browse-> find that DLL (http://ndde.codeplex.com/ from binary folder.))
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"));
}
}
}
}
Below code work pretty well with Chrome Version 58.0.3029.110:
Please add reference of UIAutomationClient and UIAutomationProvider from Assembly provided by .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);
}