繁体   English   中英

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

[英]Retrieve current URL from C# windows forms application

我一直在使用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;
    }
}

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

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

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

这是基于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工具来了解所有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);
    }
}

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

Mourier,感谢您的解决方案Microsoft UI Automation 即使如此,它对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;
        }

以下是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显示Firefox窗口控件结构。 名为“搜索或输入地址”的“编辑”类型控件包含以下网址: 自动化间谍

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

  • UIAutomationClient.dll
  • UIAutomationTypes.dll

这是我到目前为止(虽然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();
    }
}

选择是使用selenium webdriver。 最佳和功率完整的api与完整的首映

IE中支持WWW_GetWindowInfo,并且 16位以来版本已经恢复到3.02版本 适用于Firefox和Opera

我相信Chrome实际上是奇怪的。

我不知道事情是如何超越这四个。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM