从C#窗体窗体应用程序中检索当前的URL
我一直在使用Visual C#devise一个程序,并遇到了一个问题,使我的程序与网页浏览器交互。 基本上我需要的是从networking浏览器(Internet Explorer,Firefox,Chrome等)检索URL地址。
我觉得这个任务不会太困难,但经过几天的研究和testing,看起来几乎是不可能的! 到目前为止,我遇到了这个…
获取Firefoxurl?
其中有以下代码:
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; } }
这是Firefox的完美,但由于某种原因,我不能让它与其他任何工作。 我已经将代码中的“Firefox”部分更改为“Iexplore”,就像我在互联网上发现的一样,并尝试其他forms的Internet Explorer,我得到以下错误:
“客户端无法连接到”IExplorer | WWW_GetWindowInfo“,请确保服务器应用程序正在运行,并且它支持指定的服务名称和主题名称对”
任何有关这个问题的帮助将非常感激,因为它已成为一个相当的任务搞清楚。
这是我迄今为止(虽然铬我没有find任何有用的文章,除了使用FindWindowEx(我不特别喜欢这种方法,个人)。
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(); } }
这是一个基于Microsoft UI自动化的代码:
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; }
您可以使用UI间谍工具来了解所有3个浏览器的视觉层次结构。 你可能需要适应一些事情,以确保它在你的特定情况下真正起作用,但你应该对这些样本有一个总体的想法。
还有一个例子,它将转储当前在系统中运行的所有3种types的进程(IE,FF,CH)的所有URL:
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); } }
在IE的oDde.Request(“URL”,int.MaxValue)中使用参数“1”而不是“URL”。
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; } }
快递,感谢您的解决schemeMicrosoft UI自动化 。 即使如此,它没有为Firefox 41.0工作,我用小工具“自动化间谍 ”分析了Firefox窗口结构。 然后,我稍微改变了search条件,它完美的工作!
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; }
这里是铬48的解决scheme:
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; }
自动化间谍显示Firefox窗口控制结构。 名称为“search或input地址”的“编辑”types的控件包含以下URL:
注意:在你的.NET项目中你需要2个引用:
- UIAutomationClient.dll
- UIAutomationTypes.dll
WWW_GetWindowInfo在IE中被支持,并且在16位的日子里已经从版本3.02开始了! 适用于Firefox和Opera
我相信Chrome实际上是奇怪的。
我不了解这四者之外的事情。
这个select是使用seleniumwebdriver。 最好的和充分的前提下,充分的api