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

如何等待WebBrowser在VB.NET中完全加载?,vb.net,webbrowser-control,Vb.net,Webbrowser Control,我在VB.NET应用程序中使用WebBrowser控件加载一些URL(~10-15),并将它们的HTML源代码保存在文本文件中。但是,我的代码并没有编写当前页面的源代码,而是编写初始页面的源代码,因为它甚至在加载页面之前就被触发了 在调用任何事件之前,如何等待页面完全加载 我尝试了下面的代码,但不起作用 Do Until WebBrowser1.ReadyState = WebBrowserReadyState.Complete Application.DoEvents() Loop 听

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

在调用任何事件之前,如何等待页面完全加载

我尝试了下面的代码,但不起作用

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

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


MSDN有几篇关于webbrowser控件的好文章-有很多例子,还有

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()
代码如下:您需要两个sub加上可访问变量,
pageready
。 首先,确保将名为
whatbrowser
的变量固定为webbrowser控件

现在,在模块或类中的某个位置,放置以下内容:

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

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

  • 在WaitForPageLoad方法中添加处理程序可能太晚了。导航是在添加处理程序之前启动的,这意味着在极少数情况下,浏览器已经拥有页面,它可能会在添加处理程序之前完成,在这种情况下,您将错过事件并永远等待

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

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

  • 好的编程实践是添加一个超时,这样丢失(或崩溃,或循环)的浏览器就不会让代码永远等待文档完成


  • 我与这个“满负荷”问题斗争了一段时间,但发现以下解决方案对我有效。我使用的是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
    
    Private子浏览器()
    在WebBrowser1.Busy或WebBrowser1.ReadyState ReadyState\u完成时执行此操作
    多芬特
    环
    端接头
    

    足够容纳浏览器。不确定这是否会帮助所有人,因为IE7、我正在加载的网站和页面单独运行的javascript的组合可能允许使用此解决方案,但肯定值得一试。

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

    在WebBrowser1.docueCompleted中,使用
    Me.Show

    我制作了类似的功能(仅对我有效);抱歉,它是C语言的,但很容易翻译

    private void WaitForPageLoad () {
    
         while (pageReady == false)
             Application.DoEvents();
    
         while (webBrowser1.IsBusy || webBrowser1.ReadyState != WebBrowserReadyState.Complete)
             Application.DoEvents();
    }
    
    等一下

    根据我的经验,您应该确保
    DocumCompleted
    属于您的URL,而不是框架子页面、脚本、图像、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
    

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

    Private Sub WebBrowser1_ProgressChanged(sender As Object, e As WebBrowserProgressChangedEventArgs) Handles WebBrowser1.ProgressChanged
    
            Console.WriteLine("Current Progress: " + e.CurrentProgress.ToString)
    
            If e.CurrentProgress = e.MaximumProgress Then
    
                ' The maximum progress is reached
                load_started = True
    
            End If
    
            ' The page is confirmed downloaded after the progress returns to 0
            If e.CurrentProgress = 0 Then
    
                If load_started Then
    
                    ' The page is ready to print or download...
                    WebBrowser1.Print()
                    load_started = False
    
                End If
    
            End If
    
    End Sub
    

    另一个选项是检查它是否正忙着使用计时器:

    默认情况下,将计时器设置为禁用。然后,无论何时导航,都要启用它。i、 e:

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

        Private Sub tmrBusy_Tick(sender As Object, e As EventArgs) Handles tmrBusy.Tick
    
            If WebBrowser1.IsBusy = True Then
    
                Debug.WriteLine("WB Busy ...")
    
            Else
    
                Debug.WriteLine("WB Done.")
                tmrBusy.Enabled = False
    
            End If
    
        End Sub
    

    在WebBrowser本身的声明中,我使用的是私有子WebBrowser 1_DocumentCompleted。当页面在WebBrowser的declarion中完全加载时,我如何实现发生的事情?@Shubham:(MSDN:“如何:编写事件处理程序”),或者看看Hans的示例。不要忘记方法声明末尾的
    Handles
    关键字。请稍候。。。让我从我的角度(见我的答案)提出一个
    DocumentCompleted
    的准确例子,我也想知道这一点。在加载过程中,Read状态通常达到4。我们只需要知道它什么时候完成。就这些了。@shubham如果你在这方面还有问题,请告诉我,因为我多年来已经开发了解决这个问题的技术,这些方法还不为人所知,也没有发表过。这个问题是整个WebBrowser控件中最重要也是最困难的问题。阅读我最近关于webbrowser控件的一些帖子(在过去几天里我做了很多),特别是关于WB控件限制的帖子,在我的下一篇评论中。基本上,我已经解决了所有的问题,如果你仍然