Obtener URL del navegador a la aplicación C #

¿Cómo puedo obtener la URL de una instancia en ejecución de Chrome u Opera usando la aplicación de formulario de windows C # .NET? ¡Gracias!

Parte 2:

Básicamente, tengo demasiado código para separar el mínimo de este ejemplo, pero he proporcionado mi propio algoritmo a continuación para que lo viertas.

Este también realiza un seguimiento de las tabs en los navegadores, a medida que reaparecen (solo IE), por lo que tendrá que quitar los bits que no desea. Parece que recuerdo que arreglé esto para IE8, pero no estoy seguro de si esa corrección entró en este código, así que no te sorprendas si necesita un pequeño ajuste 🙂

// 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; } 

Parte 1:

Si Microsoft Spy ++ puede ver el control de dirección, entonces sí es posible.

No tengo instalado Opera, pero la jerarquía de control de Chrome en Spy ++ tiene este aspecto:

texto alternativo

He hecho cosas similares con Internet Explorer:

  • Para registrar un diario de los sitios visitados, una ventana emergente le pregunta al usuario qué estaban haciendo
  • Para mostrar un widget que aparece cuando se visitaron ciertos sitios conocidos

Firefox fue el problema secundario, ya que representa la barra de direcciones internamente y no a través de un control de Windows, pero veo que ya has encontrado la solución a esa.

En C #, debe realizar llamadas no administradas a los métodos API de Windows. Como puede ver solo desde el código API de C # (a continuación), puede involucrarse un poco:

 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; } 

El algoritmo involucrado básicamente busca todas las ventanas desde el Escritorio hacia abajo hasta que encuentra las ventanas del Navegador (en función de atributos de clase o ventana específicos). Luego busca elementos secundarios específicos según el tipo de navegador. Cuando finalmente llegue al control de dirección, puede extraer la dirección del control. Espero que mi código de clase de ayuda acelere tu desarrollo.

Seguimiento de “NativeWIN32” – Dic 2013

Las referencias de NativeWIN32 refieren simplemente a una clase contenedora que contiene constantes útiles y métodos para otras características de Win32. Lo he agregado aquí en su totalidad:

 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; } 

Haga lo siguiente para ejecutar este código Agregue referencia> Com> Microsoft.Internet.Controls de VS.NET en su proyecto

Descargue el contenedor de http://ndde.codeplex.com/ para la clase DdeClient y agréguelo a su proyecto

A menos que los navegadores estén documentados para proporcionar esa información ellos mismos, no creo que haya una manera confiable de hacerlo.

Habiendo dicho eso, estoy bastante seguro de que al menos Chrome almacena información histórica en algún lugar del disco, por lo que la mejor opción es averiguar dónde, en qué formato está y cómo leerlo.

IE11, Chrome, Firefox, Opera, Safari tienen interfaces para obtener URL e incluso el DOM, o al menos el búfer de documento / HTML. FF en realidad tiene un archivo DLL con exportaciones para hacerlo por ti, me olvido de cómo hacerlo de manera confiable bajo los demás, pero sé que ya está hecho.

Otra forma de abordar este problema podría ser utilizar el marco de automatización de UI .

Este ejemplo lee la url actual de Chrome:

 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()); 

Aquí hay un excelente tutorial sobre automatización de UI.

Descubre las URL abiertas de IE

Agregue la referencia “Microsoft Internet Controls” de la pestaña COM, luego:

 using SHDocVw; 

La lista de mi directiva completa se ve así:

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

y ahora para descubrir las URL de tabs de IE, haz esto:

  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]); }