重读webbrowser窗口的内容/等待用户输入

时间:2017-02-21 09:44:59

标签: vb.net browser do-loops

在我的程序中,我想在webbrowser窗口中为2个输入字段赋值,然后等待用户单击登录按钮。在此之后,我希望程序在屏幕内容和#34;欢迎时打破循环!" (登录后包含的内容)。

但现在问题是:当设置了用户名和密码的值时,do-loop立即启动。因此,即使我单击登录按钮,循环仍然包含单击按钮之前的网页内容,它将永远循环。

我该如何解决这个问题?到目前为止,我想过两种方法:

  1. 点击按钮后重新读取html代码,以便"欢迎!"将在代码内,然后循环将中断,或
  2. 等待用户按下登录按钮。
  3. 但在这两方面我都不知道如何解决它。

    WebBrowserWindow.WebBrowser1.Navigate("[...]")
    
    Do
        If WebBrowserWindow.WebBrowser1.ReadyState = WebBrowserReadyState.Complete Then
            If WebBrowserWindow.WebBrowser1.Document.Body.InnerHtml.ToString.Contains("Login") Then Exit Do
        End If
        Application.DoEvents()
    Loop
    
    If WebBrowserWindow.WebBrowser1.Document.Body.InnerHtml.ToString.Contains("Login") Then
        WebBrowserWindow.WebBrowser1.Document.Window.Frames(2).Document.GetElementById("username").SetAttribute("value", sUser)
        WebBrowserWindow.WebBrowser1.Document.Window.Frames(2).Document.GetElementById("password").SetAttribute("value", sPass)
        Application.DoEvents()
    
        Dim DocumentCompletedHandler As WebBrowserDocumentCompletedEventHandler = Sub(dcsender As Object, dcargs As WebBrowserDocumentCompletedEventArgs)
                                                                                      If WebBrowserWindow.WebBrowser1.ReadyState = WebBrowserReadyState.Complete Then
                                                                                          RemoveHandler WebBrowserWindow.WebBrowser1.DocumentCompleted, DocumentCompletedHandler
                                                                                          'Put the code that should be executed when the user has logged in here.
                                                                                          MsgBox("it works")
                                                                                      End If
                                                                                  End Sub
    
        AddHandler WebBrowserWindow.WebBrowser1.DocumentCompleted, DocumentCompletedHandler 
    End If
    
    WebBrowserWindow.Close()
    Me.Close()
    

    当我尝试将html代码放在消息框中时,我注意到了这个问题。它只包含了旧的'代码。

    提前致谢

1 个答案:

答案 0 :(得分:2)

WinForms的黄金法则是: 永远,永远 使用Application.DoEvents()来保持您的UI响应!如果你需要使用它,那么你几乎总是做错了(参见:Keeping your UI Responsive and the Dangers of Application.DoEvents)。

不应该在UI线程上进行繁重的操作,而是在后台线程中。有多种方法可以完成UI的工作,例如TasksThreads或使用BackgroundWorker

但是在这种情况下,您甚至不需要循环。每次页面(或页面内的WebBrowser)完全加载时,iframe都会生成DocumentCompleted event。用它来知道何时执行你的代码。

说完了,请按照以下方式将其迁移到DocumentCompleted

WebBrowserWindow.WebBrowser1.Document.Window.Frames(2).Document.GetElementById("username").SetAttribute("value", sUser)
WebBrowserWindow.WebBrowser1.Document.Window.Frames(2).Document.GetElementById("password").SetAttribute("value", sPass)

Dim DocumentCompletedHandler As WebBrowserDocumentCompletedEventHandler = _
    Sub(dcsender As Object, dcargs As WebBrowserDocumentCompletedEventArgs)
        If WebBrowserWindow.WebBrowser1.ReadyState = WebBrowserReadyState.Complete Then
            RemoveHandler WebBrowserWindow.WebBrowser1.DocumentCompleted, DocumentCompletedHandler
            'Put the code that should be executed when the user has logged in here.
        End If
    End Sub

AddHandler WebBrowserWindow.WebBrowser1.DocumentCompleted, DocumentCompletedHandler

'Any code put here won't wait for the user to log in, it wil be executed pretty much immediately.

这是一个小测试项目:http://www.mydoomsite.com/sourcecodes/WebBrowser_WaitForUserInteraction.zip

最终,您的整个代码可以更改为:

WebBrowserWindow.WebBrowser1.Navigate("[...]")

Dim FirstDocumentCompletedHandler As WebBrowserDocumentCompletedEventHandler = _
    Sub()
        'Check if:
        ' - The web browser has finished loading.
        ' - WebBrowser1.Document is not Null.
        ' - WebBrowser1.Document.Body is not Null.
        ' - WebBrowser1.Document.Body.InnerHtml is not Null.
        ' - WebBrowser1.Document.Body.InnerHtml contains "Login".
        If WebBrowserWindow.WebBrowser1.ReadyState = WebBrowserReadyState.Complete AndAlso _
            WebBrowserWindow.WebBrowser1.Document IsNot Nothing AndAlso _
             WebBrowserWindow.WebBrowser1.Document.Body IsNot Nothing AndAlso _
              WebBrowserWindow.WebBrowser1.Document.Body.InnerHtml IsNot Nothing AndAlso _
               WebBrowserWindow.WebBrowser1.Document.Body.InnerHtml.Contains("Login") Then

            'The code put in here will execute when the page loads the first time, and the above conditions are met.

            'We are at the login page. Enter the credentials.
            WebBrowserWindow.WebBrowser1.Document.Window.Frames(2).Document.GetElementById("username").SetAttribute("value", sUser)
            WebBrowserWindow.WebBrowser1.Document.Window.Frames(2).Document.GetElementById("password").SetAttribute("value", sPass)

            Dim SecondDocumentCompletedHandler As WebBrowserDocumentCompletedEventHandler = _
                Sub(dcsender As Object, dcargs As WebBrowserDocumentCompletedEventArgs)

                    If WebBrowserWindow.WebBrowser1.ReadyState = WebBrowserReadyState.Complete Then
                        RemoveHandler WebBrowserWindow.WebBrowser1.DocumentCompleted, SecondDocumentCompletedHandler

                        'The code put in here will be executed after the user has pressed "Login".
                        MsgBox("it works")
                        WebBrowserWindow.Close()
                        Me.Close()

                    End If

                End Sub

            AddHandler WebBrowserWindow.WebBrowser1.DocumentCompleted, SecondDocumentCompletedHandler 'Add the second DocumentCompleted event handler.
            RemoveHandler WebBrowserWindow.WebBrowser1.DocumentCompleted, FirstDocumentCompletedHandler 'Remove the first DocumentCompleted event handler.

        End If
    End Sub

AddHandler WebBrowserWindow.WebBrowser1.DocumentCompleted, FirstDocumentCompletedHandler

'Again, any code put here will execute almost immediately, thus NOT waiting for the page to load.

替代地

...如果你觉得到处都有lambdas太乱了,你可以回到使用常规方法:

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    WebBrowserWindow.WebBrowser1.Navigate("[...]")
    AddHandler WebBrowserWindow.WebBrowser1.DocumentCompleted, AddressOf WebBrowserWindow_FirstDocumentCompleted
End Sub

Private Sub WebBrowserWindow_FirstDocumentCompleted(sender As System.Object, e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs)
    'Check if:
    ' - The web browser has finished loading.
    ' - WebBrowser1.Document is not Null.
    ' - WebBrowser1.Document.Body is not Null.
    ' - WebBrowser1.Document.Body.InnerHtml is not Null.
    ' - WebBrowser1.Document.Body.InnerHtml contains "Login".
    If WebBrowserWindow.WebBrowser1.ReadyState = WebBrowserReadyState.Complete AndAlso _
        WebBrowserWindow.WebBrowser1.Document IsNot Nothing AndAlso _
         WebBrowserWindow.WebBrowser1.Document.Body IsNot Nothing AndAlso _
          WebBrowserWindow.WebBrowser1.Document.Body.InnerHtml IsNot Nothing AndAlso _
           WebBrowserWindow.WebBrowser1.Document.Body.InnerHtml.Contains("Login") Then

        'We are at the login page. Enter the credentials.
        WebBrowserWindow.WebBrowser1.Document.Window.Frames(2).Document.GetElementById("username").SetAttribute("value", sUser)
        WebBrowserWindow.WebBrowser1.Document.Window.Frames(2).Document.GetElementById("password").SetAttribute("value", sPass)

        AddHandler WebBrowserWindow.WebBrowser1.DocumentCompleted, AddressOf WebBrowserWindow_SecondDocumentCompleted 'Add the second DocumentCompleted event handler.
        RemoveHandler WebBrowserWindow.WebBrowser1.DocumentCompleted, AddressOf WebBrowserWindow_FirstDocumentCompleted 'Remove the first DocumentCompleted event handler.

    End If
End Sub

Private Sub WebBrowserWindow_SecondDocumentCompleted(sender As System.Object, e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs)
    If WebBrowserWindow.WebBrowser1.ReadyState = WebBrowserReadyState.Complete Then
        RemoveHandler WebBrowserWindow.WebBrowser1.DocumentCompleted, AddressOf WebBrowserWindow_SecondDocumentCompleted

        'Put the code that should be executed when the user has logged in here.
        MsgBox("it works")
        WebBrowserWindow.Close()
        Me.Close()

    End If
End Sub