从C#windows窗体应用程序中检索当前URL

Sto*_*now 10 .net c# url

我一直在使用Visual C#设计程序,并且遇到了使我的程序与Web浏览器交互的问题.基本上我需要的是从Web浏览器(Internet Explorer,Firefox,Chrome等)中检索URL地址.

我认为这不是一项任务太难,但经过数天和数天的研究和测试,似乎几乎不可能!到目前为止,我遇到过这个......

获取Firefox URL?

其中包含以下代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这对于Firefox来说是完美的,但由于某种原因,我不能让它与其他任何东西一起工作.我已经将代码"Firefox"的部分更改为"Iexplore",就像我在互联网上找到的一样,并尝试其他形式的表达Internet Explorer,我收到以下错误:

"客户端无法连接到"IExplorer | WWW_GetWindowInfo",请确保服务器应用程序正在运行,并且它支持指定的服务名称和主题名称对"

任何关于这个问题的帮助都会受到高度赞赏,因为它已成为一项非常重要的任务.

Sim*_*ier 20

这是基于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;
}
Run Code Online (Sandbox Code Playgroud)

您可以使用UI Spy工具来了解所有3个浏览器的可视层次结构.您可能需要调整一些事项以确保它在您的特定情况下真正起作用,但您应该对这些样本有所了解.

并且转储当前在系统中运行的所有3种类型的进程(IE,FF,CH)的所有URL的示例:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 糟糕,无视最后的评论.无论如何我都要离开它以防其他人遇到这个帖子并犯下我刚才犯的同样愚蠢的错误.当我需要添加所有引用时(我没有看到),我只添加了UIAutomation客户端引用.我现在要乱用代码,看看情况如何!我很快就会回复.再次感谢大家的帮助. (2认同)

小智 7

Mourier,感谢您提供Microsoft UI 自动化解决方案。即便如此,它也不适用于 Firefox 41.0,我使用小工具“Automation Spy ”分析了 Firefox 窗口结构。然后我稍微改变了搜索条件,它工作得很好!

 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;
        }
Run Code Online (Sandbox Code Playgroud)

这是 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;
    }
Run Code Online (Sandbox Code Playgroud)

Automation Spy 显示 Firefox 窗口控件结构。名称为“搜索或输入地址”的“编辑”类型控件包含 url: 自动化间谍

注意:在您的 .NET 项目中,您需要 2 个引用:

  • UIAutomationClient.dll
  • UIAutomationTypes.dll


小智 6

在IE的oDde.Request("URL",int.MaxValue)中使用参数"1"而不是"URL".

    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;
        }
    }
Run Code Online (Sandbox Code Playgroud)


Bra*_*tie 4

这是我到目前为止所拥有的(尽管除了使用 FindWindowEx 之外,我在 Chrome 上没有找到任何有用的文章(我个人并不特别喜欢这种方法)。

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();
    }
}
Run Code Online (Sandbox Code Playgroud)