.NET C#: WebBrowser控件的Navigate()方法无法加载目标URL

16

我正在尝试使用WebBrowser控件以编程方式加载网页,目的是测试该页面及其JavaScript函数。基本上,我想通过此控件运行的HTML和JavaScript与已知输出进行比较,以确定是否存在问题。

但是,我遇到了一些问题,无法简单地创建和导航WebBrowser控件。下面的代码旨在将HtmlDocument加载到WebBrowser.Document属性中:

WebBrowser wb = new WebBrowser();
wb.AllowNavigation = true;

wb.Navigate("http://www.google.com/");

在调用Navigate()后通过Intellisense检查Web浏览器的状态时,WebBrowser.ReadyState为“未初始化”,WebBrowser.Document = null,整体上看起来完全没有受到我的调用的影响。

在语境下,我正在一个Windows窗体对象外运行此控件:我不需要加载窗口或实际查看页面。要求指定需要执行页面的JavaScript并检查生成的HTML。

非常感谢您提供任何建议!


你是否有防火墙可能会阻止请求?请参见http://channel9.msdn.com/forums/TechOff/253431-WebBrowser-Ctrl-in-MFC/。 - Chris Shouts
Windows 防火墙已关闭(我们有路由器防火墙),这是一台开发计算机。我以前已经做过很多这样的请求(TCP,HTTP等),没有出现问题,所以我不确定这是否是安全问题。 - Dave
我添加了一个简单的示例,展示如何从控制台应用程序中处理这个问题。 - Chris Taylor
4个回答

19

你应该处理WebBrowser.DocumentComplete事件,一旦该事件被触发,你将拥有Document等。

wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);


private void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
  WebBrowser wb = sender as WebBrowser;
  // wb.Document is not null at this point
}

这是一个完整的示例,我在Windows Forms应用程序中快速编写并进行了测试。

public partial class Form1 : Form
  {
    public Form1()
    {      
      InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
      WebBrowser wb = new WebBrowser();
      wb.AllowNavigation = true;

      wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);

      wb.Navigate("http://www.google.com");

              }

    private void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
      WebBrowser wb = sender as WebBrowser;
      // wb.Document is not null at this point
    }
  }

编辑:这里是一个简单的代码版本,可以从控制台应用程序中运行窗口。当然,您可以进一步将事件公开给控制台代码等。

using System;
using System.Windows;
using System.Windows.Forms;

namespace ConsoleApplication1
{
  class Program
  {    
    [STAThread] 
    static void Main(string[] args)
    {      
      Application.Run(new BrowserWindow());   

      Console.ReadKey();
    }
  }

  class BrowserWindow : Form
  {
    public BrowserWindow()
    {
      ShowInTaskbar = false;
      WindowState = FormWindowState.Minimized;
      Load += new EventHandler(Window_Load);
    }

    void Window_Load(object sender, EventArgs e)
    {      
      WebBrowser wb = new WebBrowser();
      wb.AllowNavigation = true;
      wb.DocumentCompleted += wb_DocumentCompleted;
      wb.Navigate("http://www.bing.com");      
    }

    void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
      Console.WriteLine("We have Bing");
    }
  }
}

1
很遗憾,这并不起作用。 Web浏览器似乎甚至没有尝试加载该页面。将此代码添加到我的原始片段中会导致DocumentCompleted事件从未被调用,程序退出。 - Dave
@Dave,这很奇怪。我附上了一段完整的代码,并快速测试以确认它可以工作。 - Chris Taylor
@Dave,问题在于控制台应用程序没有消息泵来处理消息。 - Chris Taylor
@Dave,我添加了一个简单的示例,展示如何从控制台应用程序中处理这个问题。 - Chris Taylor
@Chris,对于我的目的来说,控制台版本的代码效果要好得多,并且我能够在事件处理程序中获取HTML。然而,它似乎没有像我希望的那样运行页面中嵌入的JavaScript。尽管如此,这个解决方案绕过了其中的一个挑战,非常感谢! - Dave
显示剩余3条评论

3

你可能需要将控件托管在父窗口中。你可以通过将承载浏览器控件的窗口移出屏幕而不显示它来实现此操作,而不会违反要求。对于开发人员而言,这也可能有用,以便进行测试、验证等,看到它确实加载了某些内容。

因此,请尝试:

// in a form's Load handler:

WebBrowser wb = new WebBrowser();
this.Controls.Add(wb);
wb.AllowNavigation = true;
wb.Navigate("http://www.google.com/");

还要检查在通过IDE实例化WebBrowser对象时设置了哪些其他属性。例如,创建一个表单,在其上放置一个浏览器控件,然后检查该表单的设计文件以查看生成的代码。您可能会错过一些需要设置的关键属性。我通过这种方式发现了许多遗漏,并学会了如何正确地以编程方式实例化可视对象。
附言:如果您使用主机窗口,它应仅在开发期间可见。您将以某种方式在生产中隐藏它。
另一种方法:
您可以尝试“原始”方法,例如:
 System.Net.WebClient wc = new System.Net.WebClient();

  System.IO.StreamReader webReader = new System.IO.StreamReader(
         wc.OpenRead("http://your_website.com"));

  string webPageData = webReader.ReadToEnd();

如果你需要的是解析网页数据中的内容,可以使用正则表达式或解析webPageData。如果你需要在页面中执行jscript(这应该是.NET 4.0可以实现的),那么你就需要它。


重要的是要注意,我还在一个[STAThread]下运行此应用程序(该程序的入口具有此指令)。否则,将抛出关于ActiveX和STAThreads仅受支持的异常。在创建WebBrowser的同一函数中,我还尝试创建一个表单并将WebBrowser控件放置在该表单中。像:WebBrowser wb = new WebBrowser(); Form f = new Form(); f.Controls.Add(wb);仅保留这个然后尝试导航什么也不做。显示窗口然后尝试导航什么也不做。 - Dave
由于该应用需要每天运行1000多个测试,使用窗体和窗口将导致不切实际。如果使用Web浏览器运行这些测试(如果可行),让某人坐在那里观察每个页面的加载将是不切实际的。因此,为了避免这种情况,需要考虑其他解决方案。 - Dave
@Paul,针对你的“另一种方法”部分,原始格式是可以的,但是我确实需要页面上的jscript执行。这个应用程序测试的页面中嵌入的jscript是否适当地修改了文档,这是一个特别感兴趣的问题。 - Dave

2

我曾经遇到过这个问题,但当时我没有意识到自己已经卸载了Internet Explorer。如果你也卸载了它,那么WebBrowser控件将不会起作用,因为它只能启动IE浏览器。


实际上,情况恰恰相反 - IE 实例化了与 WebBrowser 控件相同的引擎 :) - Lynn Crumbling

0

WebBrowser控件只是Internet Explorer的一个包装器。

您可以将其设置为不可见的Windows Forms窗口以完全实例化它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接