I have created a window form application.
This App get the active url of browser and save this into the text file.
And this works fine in chrome & IE.
But when i use firefox, this will not work. This code fails to get the active url of firefox browser.
I don't know why this happening.
I am using the following code to find the URL
public string GetBrowsedUrl()
{
IntPtr hwnd = APIFuncs.getforegroundWindow();
Int32 pid = APIFuncs.GetWindowProcessID(hwnd);
Process process = Process.GetProcessById(pid);
string appId = proc.Id.ToString();
string appName = proc.ProcessName;
string appltitle = APIFuncs.ActiveApplTitle().Trim().Replace("\0", "");
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.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
string result = ((ValuePattern)edit.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
return result;
}
Finally i found the answer
public string GetBrowsedUrl(Process process)
{
if (process.ProcessName == "firefox")
{
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 doc = element.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
if (doc == null)
return null;
return ((ValuePattern)doc.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
else
{
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.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
string result = ((ValuePattern)edit.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
return result;
}
}
You can not use this code for firefox too.
I recommend a third party library named NDde to do this very easily.
Here is NDde link
public string GetFirefoxUrl()
{
try
{
Process[] pname = Process.GetProcessesByName("Firefox");
if (pname.Length != 0)
{
DdeClient dde = new DdeClient("Firefox", "WWW_GetWindowInfo");
dde.Connect();
string url = dde.Request("URL", int.MaxValue);
url= url.Replace("\"", "").Replace("\0", "");
dde.Disconnect();
return url;
}
else
return null;
}
catch
{
return null;
}
}
Related
Hi i have a winForms application which runs a 10 sec threading timer and in that function i am calling this function whenever active process is chrome but it start with low system memory of 28 mb and goes upto 500-600mb with in hours if i use chrome constantly can someone tell what i am doing wrong
public string ChromeTabItemURL()
{
try
{
// Url Tracking Enable and Disabled From Web
if (!TrackDayWiseHelper.isTrackDayWiseActivated())
return string.Empty;
if (StorageBag.isUserDisableUrlTrack)
return string.Empty;
Process[] procsChrome = Process.GetProcessesByName("chrome");
if (procsChrome.Length == 0)
{
return "";
}
AutomationElement elm = null;
AutomationElement elmUrlBar = null;
AutomationPattern[] patterns = null;
foreach (Process chrome in procsChrome)
{
// the chrome process must have a window
if (chrome.MainWindowHandle == IntPtr.Zero)
{
continue;
}
// find the automation element
elm = AutomationElement.FromHandle(chrome.MainWindowHandle);
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)
{
if ((bool)elmUrlBar.GetCurrentPropertyValue(AutomationElement.HasKeyboardFocusProperty))
{
continue;
}
patterns = elmUrlBar.GetSupportedPatterns();
if (patterns.Length > 0)
{
ValuePattern val = (ValuePattern)elmUrlBar.GetCurrentPattern(patterns[0]);
elmUrlBar = null;
if (val.Current.Value != "")
{
if (Regex.IsMatch(val.Current.Value, #"^(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 (!val.Current.Value.StartsWith("http"))
{
string value = "http://" + val.Current.Value;
Console.WriteLine(value);
return value;
}
}
}
return val.Current.Value;
}
elmUrlBar = null;
}
}
procsChrome = null;
elm = null;
elmUrlBar = null;
patterns = null;
return "";
}
catch (System.ComponentModel.Win32Exception ex)
{
ExceptionLogging.SendExcepToDB(ex); Crashes.TrackError(ex);
}
catch (Exception ex)
{
ExceptionLogging.SendExcepToDB(ex); Crashes.TrackError(ex);
}
return "";
}
code seems to be working fine i tried using jettbrains dott trace and this didnt come up as most resource consuming process but dont know why it is happening if i run application without this everything seems to be working fine
I am currently using UIA to get the URL from Chrome, Firefox and IE11 using the following method:
string processName = "";
if (browser.Equals(BrowserType.GOOGLE_CHROME))
processName = "chrome";
else if (browser.Equals(BrowserType.FIREFOX))
processName = "firefox";
else if (browser.Equals(BrowserType.INTERNET_EXPLORER))
processName = "iexplore";
else if (browser.Equals(BrowserType.MICROSOFT_EDGE))
processName = "MicrosoftEdgeCP";
foreach(Process process in Process.GetProcessesByName(processName))
{
string url = GetURLFromProcess(process, browser);
if (url == null)
continue;
return url;
}
...
private string GetURLFromProcess(Process process, BrowserType browser)
{
if (process == null)
throw new ArgumentNullException("process");
if (process.MainWindowHandle == IntPtr.Zero)
return null;
AutomationElement elm = AutomationElement.FromHandle(process.MainWindowHandle);
if (elm == null)
return null;
string nameProperty = "";
if (browser.Equals(BrowserType.GOOGLE_CHROME))
nameProperty = "Address and search bar";
else if (browser.Equals(BrowserType.FIREFOX))
nameProperty = "Search or enter address";
else if (browser.Equals(BrowserType.INTERNET_EXPLORER))
nameProperty = "Address and search using Bing";
else if (browser.Equals(BrowserType.MICROSOFT_EDGE))
nameProperty = "Search or enter web address";
AutomationElement elmUrlBar = elm.FindFirst(TreeScope.Subtree, new AndCondition(
new PropertyCondition(AutomationElement.NameProperty, nameProperty, PropertyConditionFlags.IgnoreCase),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit)));
if (elmUrlBar != null)
{
return ((ValuePattern)elmUrlBar.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
return null;
}
Using Inspect, I can see that the URL bar in Edge is identified by 'Search or enter web address'. However, although the above method is working for other web browsers, this doesn't seem to be the case with Edge.
'elmUrlBar' always ends up being null and doesn't get found.
This code works in the last version Firefox, Internet Explorer, MS Edge and Chrome. This method works faster, than find address bar by name. And this method doesn't depend on localization of system.
private string GetURLFromProcess(Process process, BrowserType browser)
{
if (process == null)
throw new ArgumentNullException("process");
if (process.MainWindowHandle == IntPtr.Zero)
return null;
AutomationElement elm = AutomationElement.FromHandle(process.MainWindowHandle);
if (elm == null)
return null;
string nameProperty = "";
if (browser.Equals(BrowserType.GOOGLE_CHROME))
{
var elm1 = elm.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Google Chrome"));
if (elm1 == null) { return null; } // not the right chrome.exe
var elm2 = elm1.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, ""))[1];
var elm3 = elm2.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, ""))[1];
var elm4 = elm3.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, ""))[1];
var elm5 = elm4.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, ""));
var elmUrlBar = elm5.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
var url = ((ValuePattern)elmUrlBar.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
return url;
}
else if (browser.Equals(BrowserType.FIREFOX))
{
AutomationElement elm2 = elm.FindFirst(TreeScope.Children, new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ToolBar),
new PropertyCondition(AutomationElement.IsInvokePatternAvailableProperty, false)));
if (elm2 == null)
return null;
var elm3 = elm2.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ComboBox));
if (elm3 == null)
return null;
var elmUrlBar = elm3.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
if (elmUrlBar != null)
{
var url = ((ValuePattern)elmUrlBar.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
url;
}
}
else if (browser.Equals(BrowserType.INTERNET_EXPLORER))
{
AutomationElement elm2 = elm.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "ReBarWindow32"));
if (elm2 == null)
return null;
AutomationElement elmUrlBar = elm2.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
var url = ((ValuePattern)elmUrlBar.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
return url;
}
else if (browser.Equals(BrowserType.MICROSOFT_EDGE))
{
var elm2 = elm.FindFirst(TreeScope.Children, new AndCondition(
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window),
new PropertyCondition(AutomationElement.NameProperty, "Microsoft Edge")));
var elmUrlBar = elm2.FindFirst(TreeScope.Children,
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
var url = ((TextPattern)elmUrlBar.GetCurrentPattern(TextPattern.Pattern)).DocumentRange.GetText(int.MaxValue);
return url;
}
return null;
}
What is the Query results window's global service (interface)? Code below:
var dteService = Package.GetGlobalService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
if (dteService == null)
{
Debug.WriteLine("");
return;
}
var something=Package.GetGlobalService(typeof(???)) as ???;
EDIT: The goal is, when I press the context menu button, I want the function callback to be able to access the service where the work item is selected (or the results list
Please check this case in MSDN forum for the details how to get it work: https://social.msdn.microsoft.com/Forums/vstudio/en-US/2d158b9c-dec1-4c59-82aa-f1f2312d770b/sdk-packageget-selected-item-from-query-results-list
The following code is quoted from above link for your quick reference:
Document activeDocument = _applicationObject.ActiveDocument;
if (activeDocument != null)
{
DocumentService globalService = (DocumentService)Package.GetGlobalService(typeof(DocumentService));
if (globalService != null)
{
string fullName = activeDocument.FullName;
IWorkItemTrackingDocument document2 = globalService.FindDocument(fullName, null);
if ((document2 != null) && (document2 is IResultsDocument))
{
int[] selectedItemIds = ((IResultsDocument)document2).SelectedItemIds;
}
}
}
var dteService = Package.GetGlobalService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
if (dteService == null)
{
Debug.WriteLine("");
return;
}
DocumentService documentService = Package.GetGlobalService(typeof(DocumentService)) as DocumentService;
if (documentService == null)
return;
string fullName = dteService.ActiveDocument.FullName;
IWorkItemTrackingDocument activeDocument = documentService.FindDocument(fullName, null);
if (activeDocument == null || !(activeDocument is IResultsDocument))
return;
I have been designing a program using Visual C# and have came across an issue with making my program interact with web browsers. Basically what I need is to retrieve the URL address from a web browser (Internet Explorer, Firefox, Chrome etc...).
I figured this wouldn't be too difficult of a task, but after days and days of research and tests, it seems almost impossible! Thus far, I have come across this...
Get Firefox URL?
Which has the code below:
using NDde.Client;
Class Test
{
public static string GetFirefoxURL()
{
DdeClient dde = new DdeClient("Firefox", "WWW_GetWindowInfo");
dde.Connect();
string url = dde.Request("URL", int.MaxValue);
dde.Disconnect();
return url;
}
}
Which is perfect for Firefox, but for some reason I cannot get it to work with anything else. I have changed the portion of the code that says "Firefox" to "Iexplore" like I found all over the internet, along with trying other forms of expressing Internet Explorer, and I get the following error:
"Client failed to connect to "IExplorer|WWW_GetWindowInfo", Make sure the server application is running and that it supports the specified service name and topic name pair"
Any help on the issue would be much appreciated as it has become quite a task to figure out.
Here is a code based on Microsoft UI Automation:
public static string GetChromeUrl(Process process)
{
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.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
return ((ValuePattern)edit.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
public static string GetInternetExplorerUrl(Process process)
{
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 rebar = element.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "ReBarWindow32"));
if (rebar == null)
return null;
AutomationElement edit = rebar.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
return ((ValuePattern)edit.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
public static string GetFirefoxUrl(Process process)
{
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 doc = element.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
if (doc == null)
return null;
return ((ValuePattern)doc.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
You can use the UI Spy tool to understand the visual hierarchy for all 3 browsers. You may need to adapt things to make sure it really work in your specific cases, but you should get the general idea with these samples.
And an example that dumps all urls for all the 3 types of process (IE, FF, CH) currently running in the system:
static void Main(string[] args)
{
foreach (Process process in Process.GetProcessesByName("firefox"))
{
string url = GetFirefoxUrl(process);
if (url == null)
continue;
Console.WriteLine("FF Url for '" + process.MainWindowTitle + "' is " + url);
}
foreach (Process process in Process.GetProcessesByName("iexplore"))
{
string url = GetInternetExplorerUrl(process);
if (url == null)
continue;
Console.WriteLine("IE Url for '" + process.MainWindowTitle + "' is " + url);
}
foreach (Process process in Process.GetProcessesByName("chrome"))
{
string url = GetChromeUrl(process);
if (url == null)
continue;
Console.WriteLine("CH Url for '" + process.MainWindowTitle + "' is " + url);
}
}
Mourier, thank you for your solution Microsoft UI Automation.
Even so it didn't worked for Firefox 41.0,
I analysed the Firefox window structure with the little tool "Automation Spy".
Then I've changed the search conditions slightly, and it worked perfectly!
public static string GetFirefoxUrl(Process process)
{
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;
element = element.FindFirst(TreeScope.Subtree,
new AndCondition(
new PropertyCondition(AutomationElement.NameProperty, "search or enter address", PropertyConditionFlags.IgnoreCase),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit)));
if (element == null)
return null;
return ((ValuePattern)element.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
And here is the solution for Chromium 48:
public static string GetChromeUrl(Process process)
{
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)));
return ((ValuePattern)edit.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
}
Automation Spy shows Firefox window controls structure. The control of type 'edit' with the name 'Search or enter address' holds the url:
Note: In your .NET project you need 2 references:
UIAutomationClient.dll
UIAutomationTypes.dll
Use parameter "1" instead of "URL" in oDde.Request("URL", int.MaxValue) for IE.
public static void ProcessIEURLs()
{
string sURL;
try
{
DdeClient oDde = new DdeClient("IExplore", "WWW_GetWindowInfo");
try
{
oDde.Connect();
sURL = oDde.Request("1", int.MaxValue);
oDde.Disconnect();
bool bVisited = false;
if ( oVisitedURLList != null && oVisitedURLList.Count > 0 )
{
bVisited = FindURL(sURL, oVisitedURLList);
}
if ( !bVisited )
{
oVisitedURLList.Add(sURL);
}
}
catch ( Exception ex )
{
throw ex;
}
}
catch ( Exception ex )
{
throw ex;
}
}
Here's what I have so far (though Chrome I'm not finding any helpful articles on, other than using FindWindowEx (I don't particularly like that method, personally).
public class BrowserLocation
{
/// <summary>
/// Structure to hold the details regarding a browed location
/// </summary>
public struct URLDetails
{
/// <summary>
/// URL (location)
/// </summary>
public String URL;
/// <summary>
/// Document title
/// </summary>
public String Title;
}
#region Internet Explorer
// requires the following DLL added as a reference:
// C:\Windows\System32\shdocvw.dll
/// <summary>
/// Retrieve the current open URLs in Internet Explorer
/// </summary>
/// <returns></returns>
public static URLDetails[] InternetExplorer()
{
System.Collections.Generic.List<URLDetails> URLs = new System.Collections.Generic.List<URLDetails>();
var shellWindows = new SHDocVw.ShellWindows();
foreach (SHDocVw.InternetExplorer ie in shellWindows)
URLs.Add(new URLDetails() { URL = ie.LocationURL, Title = ie.LocationName });
return URLs.ToArray();
}
#endregion
#region Firefox
// This requires NDde
// http://ndde.codeplex.com/
public static URLDetails[] Firefox()
{
NDde.Client.DdeClient dde = new NDde.Client.DdeClient("Firefox", "WWW_GetWindowInfo");
try
{
dde.Connect();
String url = dde.Request("URL", Int32.MaxValue);
dde.Disconnect();
Int32 stop = url.IndexOf('"', 1);
return new URLDetails[]{
new URLDetails()
{
URL = url.Substring(1, stop - 1),
Title = url.Substring(stop + 3, url.Length - stop - 8)
}
};
}
catch (Exception)
{
return null;
}
}
#endregion
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Internet Explorer: ");
(new List<BrowserLocation.URLDetails>(BrowserLocation.InternetExplorer())).ForEach(u =>
{
Console.WriteLine("[{0}]\r\n{1}\r\n", u.Title, u.URL);
});
Console.WriteLine();
Console.WriteLine("Firefox:");
(new List<BrowserLocation.URLDetails>(BrowserLocation.Firefox())).ForEach(u =>
{
Console.WriteLine("[{0}]\r\n{1}\r\n", u.Title, u.URL);
});
Console.WriteLine();
}
}
WWW_GetWindowInfo is supported in IE and has been since version 3.02 back in the 16 bit days! Works for Firefox and Opera
I believe that Chrome is in fact the odd one out.
I've got no knowledge of how things are beyond those four.
the bese choice is to use selenium webdriver. best and power full api with full premision
I need to know the URL on which the user currently is.(with Firefox)
I thought of a keylogger to keep track of the URL, but what when the user clicks a link?
The title is not enough, I need the complete URL.
With IE this is easy, but with Firefox it isn't.
for IE I'm using:
private string GetUrlFromIE()
{
IntPtr windowHandle = GetForegroundWindow();
IntPtr childHandle;
String strUrlToReturn = "";
//IE's toolbar container
childHandle = FindWindowEx(windowHandle,IntPtr.Zero,"WorkerW",IntPtr.Zero);
if(childHandle != IntPtr.Zero)
{
//get a handle to address bar
childHandle = FindWindowEx(childHandle,IntPtr.Zero,"ReBarWindow32",IntPtr.Zero);
if(childHandle != IntPtr.Zero)
{
// get a handle to combo boxes
childHandle = FindWindowEx(childHandle, IntPtr.Zero, "ComboBoxEx32", IntPtr.Zero);
if(childHandle != IntPtr.Zero)
{
// get a handle to combo box
childHandle = FindWindowEx(childHandle, IntPtr.Zero, "ComboBox", IntPtr.Zero);
if(childHandle != IntPtr.Zero)
{
//get handle to edit
childHandle = FindWindowEx(childHandle, IntPtr.Zero, "Edit", IntPtr.Zero);
if (childHandle != IntPtr.Zero)
{
strUrlToReturn = GetText(childHandle);
}
}
}
}
}
return strUrlToReturn;
}
any ideas?
You can get the URL using Windows IAccessible interface.
For easy IAccessible manipulation I'll suggest to use Managed Windows API library.
You should have FireFox window handle in advance.
Here is C# code to grab the URL from FireFox:
private static string GetUrlFromFirefox(IntPtr windowHandle)
{
SystemAccessibleObject sao = SystemAccessibleObject.FromWindow(new SystemWindow(windowHandle), AccessibleObjectID.OBJID_WINDOW);
var preds = new Predicate<SystemAccessibleObject>[] {
s => s.RoleString == "application",
s => s.RoleString == "property page",
s => s.RoleString == "grouping" && s.StateString == "None",
s => s.RoleString == "property page" && s.StateString == "None",
s => s.RoleString == "browser",
s => s.RoleString == "document" && s.Visible
};
var current = sao.Children;
SystemAccessibleObject child = null;
foreach (var pred in preds)
{
child = Array.Find(current, pred);
if (child != null)
{
current = child.Children;
}
}
if (child != null)
{
return child.Value;
}
return string.Empty;
}
This works for FireFox 14.
In javascript, you can access the URL by way of
window.location.href