如何等待WebBrowser在VB.NET中完全加载?

时间:2010-07-18 12:38:00

标签: vb.net webbrowser-control

我在VB.NET应用程序中使用WebBrowser控件加载一些URL(~10-15)并将其HTML源保存在文本文件中。但是,我的代码不会写入当前页面的源而不是初始页面,因为它甚至在页面加载之前就被触发了。

在调用任何事件之前,我怎么能等到页面完全加载?

我尝试了以下代码,但它不起作用。

Do Until WebBrowser1.ReadyState = WebBrowserReadyState.Complete
   Application.DoEvents()
Loop

9 个答案:

答案 0 :(得分:20)

Salvete!我需要,简单地说,一个我可以调用的函数,让代码在继续之前等待页面加载。在网上搜索答案,并摆弄几个小时后,我想出了这个为自己解决,你提出的确切困境。我知道我在游戏中已经迟到了,但我希望将其发布给其他任何人。

用法:只需在导航调用后调用WaitForPageLoad()

whatbrowser.Navigate("http://www.google.com")
WaitForPageLoad()

另一个例子 我们没有将导航功能与页面加载相结合,因为有时您需要等待加载而不进行导航,例如,您可能需要等待加载以invokemember事件启动的页面

whatbrowser.Document.GetElementById("UserName").InnerText = whatusername
whatbrowser.Document.GetElementById("Password").InnerText = whatpassword
whatbrowser.Document.GetElementById("LoginButton").InvokeMember("click")
WaitForPageLoad()

以下是代码:您需要两个潜点加上可访问变量pageready。 首先,确保将名为whatbrowser的变量修复为您的web浏览器控件

现在,在你的模块或课堂的某个地方,放置一下:

Private Property pageready As Boolean = False

#Region "Page Loading Functions"
    Private Sub WaitForPageLoad()
        AddHandler whatbrowser.DocumentCompleted, New WebBrowserDocumentCompletedEventHandler(AddressOf PageWaiter)
        While Not pageready
            Application.DoEvents()
        End While
        pageready = False
    End Sub

    Private Sub PageWaiter(ByVal sender As Object, ByVal e As WebBrowserDocumentCompletedEventArgs)
        If whatbrowser.ReadyState = WebBrowserReadyState.Complete Then
            pageready = True
            RemoveHandler whatbrowser.DocumentCompleted, New WebBrowserDocumentCompletedEventHandler(AddressOf PageWaiter)
        End If
    End Sub

#End Region

答案 1 :(得分:7)

听起来您想要捕获webbrowser控件的DocumentCompleted事件。

MSDN有几篇关于webbrowser控件的好文章 - WebBrowser Class有很多例子,How to: Add Web Browser Capabilities to a Windows Forms Application

答案 2 :(得分:3)

从技术上讲,BGM发布的代码存在两个问题:

  1. 在WaitForPageLoad方法中添加处理程序可能为时已晚。在添加处理程序之前启动导航,这意味着在非常罕见的情况下,浏览器已经拥有页面,它可以在添加处理程序之前完成,在这种情况下,您将错过该事件并永远等待。

    解决方案是在导航开始之前添加处理程序,并在导航完成后删除它们

    这意味着WaitForPageLoad方法需要拆分为两个方法。在启动导航之前调用一个。它应该设置处理程序。第二部分进行ReadyState监控,并在“准备就绪”时进行清理。

  2. 良好的编程习惯是添加超时,以便丢失(或崩溃或循环)浏览器不会使您的代码永远等待文档完成,甚至

答案 3 :(得分:3)

有时如果使用JavaScript,DocumentComplet事件不会返回正确的答案,我会使用事件ProgressChanged

Private Sub WebBrowser1_ProgressChanged(sender As Object, e As WebBrowserProgressChangedEventArgs) _
 Handles WebBrowser1.ProgressChanged

    Console.WriteLine("CurrentProgress: " + e.CurrentProgress.ToString)
    If e.CurrentProgress = e.MaximumProgress Then
        'The maximun progres is reached
        load_stated = True
    End If
    'The page is confirmed downloaded after the pregres return to 0
    If e.CurrentProgress = 0 Then
        If load_stated Then
            'the page is ready to print or download...
            WebBrowser1.Print()
            load_stated = False
        End If
    End If
End Sub

答案 4 :(得分:1)

在加载事件中,使用Me.Hide

在WebBrowser1.DocuementCompleted中,使用Me.Show

答案 5 :(得分:1)

坚持......

根据我的经验,您应该确保DocumCompleted属于您的网址,而不是框架子网页,脚本,图片,CSS等。这与IsBusy无关或ReadyState已完成或未完成,当页面稍微复杂时,这两者通常都是不准确的。

嗯,这是我自己的个人经历,在VB.2013和IE11的工作程序上。我还要提一下,你还应该考虑兼容模式IE7,它默认在webBrowser1开启。

' Page, sub-frame or resource was totally loaded.
Private Sub webBrowser1_DocumentCompleted(sender As Object, _ 
    e As WebBrowserDocumentCompletedEventArgs) _ 
    Handles webBrowser1.DocumentCompleted

    ' Check if finally the full page was loaded (inc. sub-frames, javascripts, etc)
    If e.Url.ToString = webBrowser1.Url.ToString Then
        ' Only now you are sure!
        fullyLoaded = True
    End If

End Sub

答案 6 :(得分:0)

我在这个“满载”问题上挣扎了一段时间,但发现以下解决方案对我有用。我正在使用IE7,所以我不确定这是否适用于其他版本,但值得一看。

我将问题分成两部分;首先,我需要来自DocumentComplete事件的消息;

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
   fullyLoaded = True
End Sub

然后在我需要等到网页完全加载的代码部分中,我调用另一个执行此操作的子代码;

Private Sub holdBrowserPage()
     fullyLoaded = False
     Do While fullyLoaded = False
         DoEvents
     Loop 
     fullyLoaded = False
End Sub

此外,我还需要在等待javascript代码完成时做同样的事情。例如,当您从html下拉列表中选择一个项目时,在一个页面上,它会填充下一个下拉列表,但需要一段时间才能显示自己。在那种情况下,我发现了这个;

Private Sub holdBrowser()
Do While WebBrowser1.Busy Or WebBrowser1.ReadyState <> READYSTATE_COMPLETE
   DoEvents
Loop
End Sub

足以容纳浏览器。不确定这是否会对每个人有所帮助,作为IE7的组合,我加载的网站,以及单独运行该页面的javascript可能已经允许这个解决方案,但当然值得一试。

答案 7 :(得分:0)

另一种选择是检查计时器是否忙:

将计时器默认设置为禁用。然后,每当导航时,启用它。即:

removeItem(itemID, n) {
}

还有计时器:

WebBrowser1.Navigate("https://www.somesite.com")
tmrBusy.Enabled = True

答案 8 :(得分:-1)

我做了类似的功能(只对我有用) - 抱歉它在C#中,但很容易翻译......

private void WaitForPageLoad ( ) {
 while (pageReady == false)
     Application.DoEvents();

  while (webBrowser1.IsBusy || webBrowser1.ReadyState !=   WebBrowserReadyState.Complete)
     Application.DoEvents();
}