Получить URL из браузера в приложение C # - PullRequest
14 голосов
/ 27 августа 2010

Как я могу получить URL-адрес из запущенного экземпляра Chrome или Opera с помощью приложения Windows C # .NET form? Спасибо!

Ответы [ 6 ]

13 голосов
/ 27 августа 2010

Часть 2:

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

Этот файл также отслеживает вкладки в браузерах по мере их появления (только для IE), поэтому вам придется удалять ненужные фрагменты.Кажется, я помню, что исправил это для IE8, но не уверен, что это исправление вошло в этот код, так что не удивляйтесь, если он нуждается в небольшой настройке:)

    // Iterate all browsers and record the details
    IntPtr hWnd = IntPtr.Zero;
    NativeWIN32.EnumChildWindows(hWnd, new NativeWIN32.Win32Callback(BrowserEnumCallback), hWnd);

    /// <summary>
    /// Called back for each IE browser.
    /// </summary>
    /// <param name="hWnd"></param>
    /// <param name="lParam"></param>
    /// <returns></returns>
    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;
    }

    /// <summary>
    /// Called back for each child window in the browser
    /// </summary>
    /// <param name="hWnd"></param>
    /// <param name="lParam"></param>
    /// <returns></returns>
    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, но иерархия управления Chrome в Spy ++ выглядит следующим образом:

alt text

Я сделал аналогичные вещи с Internet Explorer:

  • Чтобы записать дневник посещенных сайтов - тогда всплывающее окно спросит пользователя, что они делают
  • Чтобы отобразить виджет, который появляется при посещении определенных известных сайтов

Firefox был проблемным потомком , поскольку он отображает адресную строку внутри, а не через элемент управления Windows, но я вижу васМы уже нашли решение этой проблемы.

В C # вам необходимо совершать неуправляемые вызовы методов Windows API.Как видно из одного только кода API C # (ниже), он может быть немного сложным:

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

/// <summary>
/// 
/// </summary>
/// <param name="hWnd">handle to destination window</param>
/// <param name="msg">message</param>
/// <param name="wParam">first message parameter</param>
/// <param name="lParam"second message parameter></param>
/// <returns></returns>
[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);

/// <summary>
/// Helper to get window classname
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
static public string GetClassName(IntPtr hWnd)
{
    NativeWIN32.STRINGBUFFER sLimitedLengthWindowTitle;
    NativeWIN32.GetClassName(hWnd, out sLimitedLengthWindowTitle, 256);
    return sLimitedLengthWindowTitle.szText;
}

/// <summary>
/// Helper to get window text
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
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;
}

Используемый алгоритм в основном ищет все окна с рабочего стола и далее, пока не найдет Browser окна (на основе определенного класса или атрибутов окна).Затем он ищет конкретные дочерние элементы в зависимости от типа браузера.Когда вы наконец доберетесь до элемента управления адресами, вы можете извлечь адрес из элемента управления.Надеюсь, мой код класса помощника ускорит вашу разработку.

Продолжение "NativeWIN32" - декабрь 2013

Ссылки NativeWIN32 - это просто класс-оболочка, содержащий полезные константы и методы для других функций Win32.Я добавил это здесь полностью:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace YourProject
{
    /// <summary>
    /// Wrapper for native win32 calls
    /// </summary>
    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);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="hWnd">handle to destination window</param>
        /// <param name="msg">message</param>
        /// <param name="wParam">first message parameter</param>
        /// <param name="lParam"second message parameter></param>
        /// <returns></returns>
        [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);

        /// <summary>
        /// Helper to get window classname
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        static public string GetClassName(IntPtr hWnd)
        {
            NativeWIN32.STRINGBUFFER sLimitedLengthWindowTitle;
            NativeWIN32.GetClassName(hWnd, out sLimitedLengthWindowTitle, 256);
            return sLimitedLengthWindowTitle.szText;
        }

        /// <summary>
        /// Helper to get window text
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        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;
        }
    }
}
4 голосов
/ 01 августа 2012
    [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;
    }

Пожалуйста, следуйте ниже, чтобы запустить этот код Добавить ссылку> Com> Microsoft.Internet.Controls из VS.NET в ваш проект

Загрузите корзину из http://ndde.codeplex.com/ для класса DdeClient и добавьте ее в свой проект

2 голосов
/ 27 августа 2010

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

При этом я почти уверен, что, по крайней мере, Chrome хранит информацию о хронологии где-то на диске, поэтому лучше всего выяснить, где, в каком формате и как ее читать.

0 голосов
/ 28 сентября 2015

Узнайте открытые URL от IE

Добавьте ссылку «Microsoft Internet Controls» на вкладке COM, затем:

using SHDocVw;

Список моих полных директив выглядит следующим образом:

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

и теперь, чтобы узнать URL-адреса вкладок в IE, сделайте следующее:

        Dictionary<int, string> ieUrlsDictionary = new Dictionary<int, string>();
        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]);
        }
0 голосов
/ 24 марта 2015

Другим способом решения этой проблемы может быть использование UI Automation framework.

Этот пример читает текущий URL 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());

Здесь - отличное руководство по автоматизации пользовательского интерфейса.

0 голосов
/ 24 декабря 2013

IE11, Chrome, Firefox, Opera, Safari имеют интерфейсы для получения URL и даже DOM, или, по крайней мере, буфер документа / HTML. FF на самом деле имеет DLL с экспортом, чтобы сделать это для вас, я забыл, как надежно сделать это под другими, но я знаю, что это сделано.

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