Получить текущий URL из приложения C # Windows Forms - PullRequest
10 голосов
/ 15 марта 2011

Я разрабатывал программу с использованием Visual C # и столкнулся с проблемой, которая заставила мою программу взаимодействовать с веб-браузерами. По сути, мне нужно получить URL-адрес из веб-браузера (Internet Explorer, Firefox, Chrome и т. Д.).

Я подумал, что это не будет слишком сложной задачей, но после нескольких дней исследований и испытаний это кажется почти невозможным! До сих пор я сталкивался с этим ...

Получить URL Firefox?

Который имеет код ниже:

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», как и во всем Интернете, и попробовал другие способы выражения Internet Explorer, и я получаю следующую ошибку:

«Клиенту не удалось подключиться к« IExplorer | WWW_GetWindowInfo », убедитесь, что приложение сервера запущено и поддерживает указанную пару имени службы и имени темы»

Любая помощь в этом вопросе будет высоко ценится, поскольку выяснить это стало непростой задачей.

Ответы [ 6 ]

20 голосов
/ 16 марта 2011

Вот код, основанный на 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;
}

Вы можете использовать UI Spy tool , чтобы понять визуальную иерархию для всех 3 браузеров. Возможно, вам придется адаптировать вещи, чтобы убедиться, что они действительно работают в ваших конкретных случаях, но вы должны получить общее представление об этих примерах.

И пример, который выводит все URL для всех 3 типов процессов (IE, FF, CH), запущенных в настоящее время в системе:

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);
    }
}
6 голосов
/ 14 июля 2011

Используйте параметр «1» вместо «URL» в oDde.Request («URL», int.MaxValue) для 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;
        }
    }
4 голосов
/ 18 октября 2015

Мурье, спасибо за ваше решение Microsoft UI Automation .Несмотря на то, что это не сработало для Firefox 41.0, я проанализировал структуру окна Firefox с помощью небольшого инструмента "Automation Spy ".Затем я немного изменил условия поиска, и он работал отлично!

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

И вот решение для 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;
    }

Spy автоматизации показывает структуру элементов управления Firefox.Элемент управления типа «edit» с именем «Search or enter address» содержит URL: Automation Spy

Примечание. В вашем .NET-проекте вам нужно 2 ссылки:

  • UIAutomationClient.dll
  • UIAutomationTypes.dll
3 голосов
/ 16 марта 2011

Вот что у меня есть (хотя в Chrome я не нахожу никаких полезных статей, кроме использования 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();
    }
}
0 голосов
/ 19 сентября 2013

лучший выбор - использовать селеновый вебдрайвер. лучший и мощный полный API с полной предпосылкой

0 голосов
/ 16 марта 2011

WWW_GetWindowInfo поддерживается в IE, а существует с версии 3.02 в 16-битных днях! Работает для Firefox и Opera

Я считаю, что Chrome на самом деле самый странный.

Я не знаю, как обстоят дела с этими четырьмя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...