从浏览器获取URL到C#应用程序

如何使用C#.NET windows窗体应用程序从正在运行的Chrome或Opera实例中获取url? 谢谢!

第2部分:

基本上我有太多的代码来分离出这个例子的最小值,但是我已经提供了下面的算法供你倾注。

这个也会跟踪浏览器中的选项卡,当它们重新出现时(仅限IE),因此您需要删除不需要的位。 我似乎记得我为IE8修复了这个,但不确定是否修复了这个代码,所以如果需要一点调整就不要感到惊讶:)

// Iterate all browsers and record the details IntPtr hWnd = IntPtr.Zero; NativeWIN32.EnumChildWindows(hWnd, new NativeWIN32.Win32Callback(BrowserEnumCallback), hWnd); ///  /// Called back for each IE browser. ///  ///  ///  ///  static bool BrowserEnumCallback(IntPtr hWnd, IntPtr lParam) { // Is this app IE? if (NativeWIN32.GetClassName(hWnd) == "IEFrame") { // If this is a new browser, add it if (!BrowserWindows.ContainsKey(hWnd)) { // Record the Browser BrowserWindow browser = new BrowserWindow() { hWnd = hWnd }; // Store the browser in the temp list and temp member TempCurrentBrowser = browser; BrowserWindows.Add(hWnd, browser); } else { // Store the browser in the temp list and temp member TempCurrentBrowser = BrowserWindows[hWnd]; } TempCurrentBrowser.WindowText = NativeWIN32.GetWindowText(hWnd); TempCurrentBrowser.Found = true; // Now that we know it is a browser, look for tabbed windows and address bar NativeWIN32.EnumChildWindows(hWnd, new NativeWIN32.Win32Callback(BrowserEnumChildrenCallback), hWnd); } return true; } ///  /// Called back for each child window in the browser ///  ///  ///  ///  static bool BrowserEnumChildrenCallback(IntPtr hWnd, IntPtr lParam) { string classname = NativeWIN32.GetClassName(hWnd); switch (classname) { // This is the main address bar case "Edit": { string url = NativeWIN32.GetWindowText(hWnd); if (url.StartsWith(@"http://") || url.StartsWith(@"https://") || url.StartsWith("about:")) { TempCurrentBrowser.Url = url; return true; } } break; case "ComboBoxEx32": { string url = NativeWIN32.GetWindowText(hWnd); if (url.StartsWith(@"http://") || url.StartsWith(@"https://") || url.StartsWith("about:")) { TempCurrentBrowser.Url = url; return true; } } break; // Record any sub pages still active, by title to avoid revisiting popup // If this name matches the name of the browser, it is the current window // If so, record the browser url for reference in that tab window case "TabWindowClass": { string title = NativeWIN32.GetWindowText(hWnd); BrowserTabWindow tabWindow; if (!TempCurrentBrowser.TabWindows.ContainsKey(hWnd)) { // Create a new tabbed window for the current browser tabWindow = new BrowserTabWindow() { hWnd = hWnd }; TempCurrentBrowser.TabWindows.Add(hWnd, tabWindow); } else { tabWindow = TempCurrentBrowser.TabWindows[hWnd]; } tabWindow.WindowText = title; tabWindow.Found = true; } break; } return true; } 

第1部分:

如果Microsoft Spy ++可以看到地址控件,那么是的。

我没有安装Opera,但Spy ++中的Chrome控件层次结构如下所示:

替代文字

我用Internet Explorer做过类似的事情:

  • 要记录访问过的网站的日记 – 然后弹出窗口会询问用户他们在做什么
  • 显示在访问某些已知站点时弹出的窗口小部件

Firefox是问题孩子,因为它在内部呈现地址栏而不是通过Windows控件,但我发现你已经找到了解决方案。

在C#中,您需要对Windows API方法进行非托管调用。 正如您可以从单独的C#API代码(下面)中看到的那样,它可能会涉及到一些问题:

 const int WM_GETTEXT = 0xD; // used for an output LPCTSTR parameter on a method call [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct STRINGBUFFER { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string szText; } [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr FindWindowEx(IntPtr parent /*HWND*/, IntPtr next /*HWND*/, string sClassName, IntPtr sWindowTitle); ///  /// ///  /// handle to destination window /// message /// first message parameter ///  ///  [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, out STRINGBUFFER ClassName); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int GetWindowText(IntPtr hWnd, out STRINGBUFFER ClassName, int nMaxCount); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int GetClassName(IntPtr hWnd, out STRINGBUFFER ClassName, int nMaxCount); //[DllImport("user32.dll")] //[return: MarshalAs(UnmanagedType.Bool)] //static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam); public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam); [DllImport("user32.Dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam); ///  /// Helper to get window classname ///  ///  ///  static public string GetClassName(IntPtr hWnd) { NativeWIN32.STRINGBUFFER sLimitedLengthWindowTitle; NativeWIN32.GetClassName(hWnd, out sLimitedLengthWindowTitle, 256); return sLimitedLengthWindowTitle.szText; } ///  /// Helper to get window text ///  ///  ///  static public string GetWindowText(IntPtr hWnd) { NativeWIN32.STRINGBUFFER sLimitedLengthWindowTitle; SendMessage(hWnd, WM_GETTEXT, 256, out sLimitedLengthWindowTitle); //NativeWIN32.GetWindowText(hWnd, out sLimitedLengthWindowTitle, 256); return sLimitedLengthWindowTitle.szText; } 

所涉及的算法基本上从桌面上搜索所有窗口,直到它找到浏览器窗口(基于特定的类或窗口属性)。 然后,它根据浏览器的类型搜索特定的子元素。 当您最终到达地址控件时,您可以从控件中提取地址。 希望我的助手类代码能加速你的开发。

“NativeWIN32”跟进 – 2013年12月

NativeWIN32引用只是一个包装类,包含有用的常量和其他Win32function的方法。 我在这里完整地添加了它:

 using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace YourProject { ///  /// Wrapper for native win32 calls ///  public class NativeWIN32 { const int WM_GETTEXT = 0xD; // used for an output LPCTSTR parameter on a method call [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct STRINGBUFFER { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string szText; } [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr FindWindowEx(IntPtr parent /*HWND*/, IntPtr next /*HWND*/, string sClassName, IntPtr sWindowTitle); ///  /// ///  /// handle to destination window /// message /// first message parameter ///  ///  [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, out STRINGBUFFER ClassName); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int GetWindowText(IntPtr hWnd, out STRINGBUFFER ClassName, int nMaxCount); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int GetClassName(IntPtr hWnd, out STRINGBUFFER ClassName, int nMaxCount); //[DllImport("user32.dll")] //[return: MarshalAs(UnmanagedType.Bool)] //static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam); public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam); [DllImport("user32.Dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam); ///  /// Helper to get window classname ///  ///  ///  static public string GetClassName(IntPtr hWnd) { NativeWIN32.STRINGBUFFER sLimitedLengthWindowTitle; NativeWIN32.GetClassName(hWnd, out sLimitedLengthWindowTitle, 256); return sLimitedLengthWindowTitle.szText; } ///  /// Helper to get window text ///  ///  ///  static public string GetWindowText(IntPtr hWnd) { NativeWIN32.STRINGBUFFER sLimitedLengthWindowTitle; SendMessage(hWnd, WM_GETTEXT, 256, out sLimitedLengthWindowTitle); //NativeWIN32.GetWindowText(hWnd, out sLimitedLengthWindowTitle, 256); return sLimitedLengthWindowTitle.szText; } } } 
  [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, StringBuilder ClassName); private static string GetURL(IntPtr intPtr, string programName, out string url) { string temp=null; if (programName.Equals("chrome")) { var hAddressBox = FindWindowEx(intPtr, IntPtr.Zero, "Chrome_OmniboxView", IntPtr.Zero); var sb = new StringBuilder(256); SendMessage(hAddressBox, 0x000D, (IntPtr)256, sb); temp = sb.ToString(); } if (programName.Equals("iexplore")) { foreach (InternetExplorer ie in new ShellWindows()) { var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(ie.FullName); if (fileNameWithoutExtension != null) { var filename = fileNameWithoutExtension.ToLower(); if (filename.Equals("iexplore")) { temp+=ie.LocationURL + " "; } } } } if (programName.Equals("firefox")) { DdeClient dde = new DdeClient("Firefox", "WWW_GetWindowInfo"); dde.Connect(); string url1 = dde.Request("URL", int.MaxValue); dde.Disconnect(); temp = url1.Replace("\"","").Replace("\0",""); } url = temp; return temp; } 

请执行以下操作以在项目中运行此代码从VS.NET添加参考> Com> Microsoft.Internet.Controls

从http://ndde.codeplex.com/下载用于DdeClient类的bin并将其添加到您的项目中

除非记录浏览器本身提供该信息,否则我认为没有可靠的方法。

话虽这么说,我很确定至少Chrome会将磁盘上的历史信息存储在磁盘上,所以最好的办法是找出它的位置,格式以及如何阅读。

IE11,Chrome,Firefox,Opera,Safari都有接口来获取URL甚至是DOM,或者至少是文档/ HTML缓冲区。 FF实际上有一个带导出的DLL来为你做,我忘了如何在其他人之下可靠地做到这一点,但我知道它已经完成了。

解决此问题的另一种方法可能是使用UI Automation框架。

此示例读取Chrome的当前url:

 var app = AutomationElement.FromHandle(new IntPtr(chrome_hwnd)); var propFindText = new PropertyCondition(AutomationElement.NameProperty, "Address and search bar"); var textbox = app.FindFirst(TreeScope.Descendants, propFindText); Debug.WriteLine( textbox.GetCurrentPropertyValue(ValuePattern.ValueProperty).ToString()); 

这是一篇关于UI自动化的优秀教程。

从IE中找到开放的Url

从COM选项卡添加引用“Microsoft Internet Controls”,然后:

 using SHDocVw; 

我的完整指令列表如下所示:

 using System; using System.Collections.Generic; using System.IO; using System.Windows.Forms; using SHDocVw; 

现在要从IE中找到标签url,请执行以下操作:

  Dictionary ieUrlsDictionary = new Dictionary(); ShellWindows ieShellWindows = new SHDocVw.ShellWindows(); string sProcessType; int i = 0; foreach (InternetExplorer ieTab in ieShellWindows) { sProcessType = Path.GetFileNameWithoutExtension(ieTab.FullName).ToLower(); if (sProcessType.Equals("iexplore") && !ieTab.LocationURL.Contains("about:Tabs")) { ieUrlsDictionary[i] = ieTab.LocationURL; i++; } } //show list of url´s for (int j = 0; j < ieUrlsDictionary.Count; j++) { Console.WriteLine(ieUrlsDictionary[j]); }