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

标签 c# .net url browser

如何使用 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);

    /// <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,但 Spy++ 中的 Chrome 控件层次结构如下所示:

alt text

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

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

Firefox 是有问题的 child ,因为它在内部而不是通过 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);

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

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

“NativeWIN32”跟进 - 2013 年 12 月

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

关于c# - 从浏览器获取 URL 到 C# 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3579649/

相关文章:

c# - 给定字体文件,如何获取字体系列的名称?

javascript - 从剪贴板解析并添加 url

python - Django-链接到另一个 View

c# - ASP.NET Web 应用程序的付款方式

c# - 在 .NET 后端移动服务的 InsertAsync 期间引发 HttpResponseException

c# - UML 转 java 或 c# 工具?

ruby-on-rails - 如何在 Rails 中设置 url 助手的默认主机?

c# - Newtonsoft 对象序列化为字符串。预期 JObject 实例

c# - 如果所有单词都包含特定符号,则为正则表达式

c# - 如何快速将两个字节添加到字节数组中?