Recuperar la URL actual de la aplicación de formularios de Windows C #

He estado diseñando un progtwig usando Visual C # y me he encontrado con un problema para hacer que mi progtwig interactúe con los navegadores web. Básicamente lo que necesito es recuperar la dirección URL de un navegador web (Internet Explorer, Firefox, Chrome, etc.).

Pensé que esto no sería una tarea demasiado difícil, pero después de días y días de investigación y pruebas, ¡parece casi imposible! Hasta ahora, me he encontrado con esto …

Obtener URL de Firefox?

Que tiene el siguiente código:

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

Lo cual es perfecto para Firefox, pero por alguna razón no puedo hacer que funcione con otra cosa. He cambiado la porción del código que dice “Firefox” a “Iexplore” como lo encontré en Internet, junto con otras formas de express Internet Explorer, y me aparece el siguiente error:

“El cliente no pudo conectarse a” IExplorer | WWW_GetWindowInfo “, asegúrese de que la aplicación del servidor se esté ejecutando y de que sea compatible con el nombre del servicio especificado y el par de nombre del tema”

Cualquier ayuda sobre el tema sería muy apreciada ya que se ha convertido en una tarea bastante difícil de descifrar.

Esto es lo que tengo hasta ahora (aunque Chrome no encuentro ningún artículo útil, aparte de usar FindWindowEx (personalmente no me gusta particularmente ese método).

 public class BrowserLocation { ///  /// Structure to hold the details regarding a browed location ///  public struct URLDetails { ///  /// URL (location) ///  public String URL; ///  /// Document title ///  public String Title; } #region Internet Explorer // requires the following DLL added as a reference: // C:\Windows\System32\shdocvw.dll ///  /// Retrieve the current open URLs in Internet Explorer ///  ///  public static URLDetails[] InternetExplorer() { System.Collections.Generic.List URLs = new System.Collections.Generic.List(); 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.InternetExplorer())).ForEach(u => { Console.WriteLine("[{0}]\r\n{1}\r\n", u.Title, u.URL); }); Console.WriteLine(); Console.WriteLine("Firefox:"); (new List(BrowserLocation.Firefox())).ForEach(u => { Console.WriteLine("[{0}]\r\n{1}\r\n", u.Title, u.URL); }); Console.WriteLine(); } } 

Aquí hay un código basado en la Automatización de UI de Microsoft :

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

Puede usar la herramienta UI Spy para comprender la jerarquía visual de los 3 navegadores. Es posible que deba adaptar las cosas para asegurarse de que realmente funcionen en sus casos específicos, pero debe obtener la idea general con estas muestras.

Y un ejemplo que vuelca todas las direcciones URL para los 3 tipos de procesos (IE, FF, CH) que se están ejecutando actualmente en el sistema:

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

Use el parámetro “1” en lugar de “URL” en oDde.Request (“URL”, int.MaxValue) para 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; } } 

Mourier, gracias por su solución Microsoft UI Automation . Aun así no funcionó para Firefox 41.0, analicé la estructura de la ventana de Firefox con la pequeña herramienta “Automation Spy “. ¡Luego modifiqué un poco las condiciones de búsqueda y funcionó perfectamente!

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

Y aquí está la solución para 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 muestra la estructura de controles de la ventana de Firefox. El control de tipo ‘editar’ con el nombre ‘Buscar o ingresar dirección’ contiene la url: Automatización Espía

Nota: en su proyecto .NET necesita 2 referencias:

  • UIAutomationClient.dll
  • UIAutomationTypes.dll

WWW_GetWindowInfo es compatible con IE y lo ha sido desde la versión 3.02 en los días de 16 bits. Funciona para Firefox y Opera

Creo que Chrome es, de hecho, el más extraño.

No tengo conocimiento de cómo están las cosas más allá de esos cuatro.

la mejor opción es usar selenium webdriver. mejor y potencia api completa con premision completo