Web 浏览器自动导航事件

webbrowser auto navigation event

我正在使用网络浏览器导航到一个网站,然后自动登录。一切正常,直到评论 "Navigating Event" 输入一个凭据后,它将登录并导航到另一个网站。在事件 none 之后,代码将起作用,因为它没有选择新站点。我正在使用 waitforpageload() 函数让我知道它何时完成加载,但是当我检查 url 时它仍然指向原始站点。知道为什么要这样做以及如何绕过它吗?

    Private Property pageready As Boolean = False

    webBrowser1.Navigate("https://www.lamedicaid.com/sprovweb1/provider_login/provider_login.asp")
            waitforpageload()

    Dim allelements As HtmlElementCollection = webBrowser1.Document.All
            For Each webpageelement As HtmlElement In allelements
                'NPI #
                If webpageelement.GetAttribute("name") = "Provider_Id" Then
                    webpageelement.SetAttribute("value", "xxxxxx")
                End If
                'Clicking enter to input NPI
                If webpageelement.GetAttribute("name") = "submit1" Then
                    webpageelement.InvokeMember("focus")
                    webpageelement.InvokeMember("click")
                    waitforpageload()
                End If

                'Navigation event happens here

                'Entering username
                If webpageelement.GetAttribute("name") = "Login_Id" Then
                    webpageelement.SetAttribute("value", "xxxxxxx")
                End If
                'Entering Password
                If webpageelement.GetAttribute("name") = "Password" Then
                    webpageelement.SetAttribute("value", "xxxxxxxxx")
                End If
                'logging in
                If webpageelement.GetAttribute("name") = "submit_button" Then
                    webpageelement.InvokeMember("focus")
                    webpageelement.InvokeMember("click")
                    waitforpageload()
                End If




    #Region "Page Loading Functions"
    Private Sub waitforpageload()
        AddHandler webBrowser1.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 webBrowser1.ReadyState = WebBrowserReadyState.Complete Then
            pageready = True
            RemoveHandler webBrowser1.DocumentCompleted, New WebBrowserDocumentCompletedEventHandler(AddressOf PageWaiter)
        End If
    End Sub
#End Region

拜托,看在上帝的份上,去掉那个waitforpageload()函数!使用 Application.DoEvents() 错误做法 并且在这样的循环中,将利用 100% 的 CPU!

最初编写该函数(来自另一个 Stack Overflow post)的人显然不知道 he/she 当时在做什么。使用 Application.DoEvents() 产生的问题多于它解决的问题,因此 永远不要 在任何人的代码中使用(它存在主要是因为它被内部方法)。

参考:Keeping your UI Responsive and the Dangers of Application.DoEvents了解更多信息。

WebBrowser 有一个专用的 DocumentCompleted event,每次页面(或页面的一部分,例如 iframe)完全加载时都会引发。

为确保页面确实完全加载,请订阅 DocumentCompleted 事件并检查 ReadyState property 是否等于 WebBrowserReadyState.Complete

为了能够在引发 DocumentCompleted 事件时 运行 编写更多 "dynamically" 代码,您可以利用 lambda expressions 作为创建内联方法的一种方式。

在你的情况下,它们可以这样使用:

'Second step (these must always be in descending order since the first step must be able to reference the second, and so on).
Dim credentialHandler As WebBrowserDocumentCompletedEventHandler = _
    Sub(wsender As Object, we As WebBrowserDocumentCompletedEventArgs)
        'If the WebBrowser HASN'T finished loading, do not continue.
        If webBrowser1.ReadyState <> WebBrowserReadyState.Complete Then Return

        'Remove the event handler to avoid this code being called twice.
        RemoveHandler webBrowser1.DocumentCompleted, credentialHandler

        'Entering username
        If webpageelement.GetAttribute("name") = "Login_Id" Then
            webpageelement.SetAttribute("value", "xxxxxxx")
        End If

        'Entering Password
        If webpageelement.GetAttribute("name") = "Password" Then
            webpageelement.SetAttribute("value", "xxxxxxxxx")
        End If

        'logging in
        If webpageelement.GetAttribute("name") = "submit_button" Then
            webpageelement.InvokeMember("focus")
            webpageelement.InvokeMember("click")
        End If
    End Sub


'First step.
Dim loginHandler As WebBrowserDocumentCompletedEventHandler = _
    Sub(wsender As Object, we As WebBrowserDocumentCompletedEventArgs)
        'If the WebBrowser hasn't finished loading, do not continue.
        If webBrowser1.ReadyState <> WebBrowserReadyState.Complete Then Return

        'Remove the event handler to avoid this code being called twice.
        RemoveHandler webBrowser1.DocumentCompleted, loginHandler

        Dim allelements As HtmlElementCollection = webBrowser1.Document.All
        For Each webpageelement As HtmlElement In allelements
            'NPI #
            If webpageelement.GetAttribute("name") = "Provider_Id" Then
                webpageelement.SetAttribute("value", "xxxxxx")
                '-- Why would you even wait in here?? There's no reason for you to wait after only changing an attribute since nothing is loaded from the internet.
            End If

            'Clicking enter to input NPI
            If webpageelement.GetAttribute("name") = "submit1" Then

                'Adding the event handler performing our next step.
                AddHandler webBrowser1.DocumentCompleted, credentialHandler

                webpageelement.InvokeMember("focus")
                webpageelement.InvokeMember("click")
            End If
        Next
    End Sub

'Add the event handler performing our first step.
AddHandler webBrowser1.DocumentCompleted, loginHandler

webBrowser1.Navigate("https://www.lamedicaid.com/sprovweb1/provider_login/provider_login.asp")

现在每次需要等待 document/website 完全加载时,只需声明一个新的 lambda 并将其作为事件处理程序添加到 DocumentCompleted:

Dim thirdStepHandler As WebBrowserDocumentCompletedEventHandler = _
    Sub(wsender As Object, we As WebBrowserDocumentCompletedEventArgs)
        'If the WebBrowser hasn't finished loading, do not continue.
        If webBrowser1.ReadyState <> WebBrowserReadyState.Complete Then Return

        'Remove the event handler to avoid this code being called twice.
        RemoveHandler webBrowser1.DocumentCompleted, thirdStepHandler

        'Your goes code here...
    End Sub


'To wait until performing the next step (be sure to do this BEFORE navigating):
AddHandler webBrowser1.DocumentCompleted, thirdStepHandler