Vb.net 重新读取webbrowser窗口的内容/等待用户输入

Vb.net 重新读取webbrowser窗口的内容/等待用户输入,vb.net,browser,do-loops,Vb.net,Browser,Do Loops,在我的程序中,我想给webbrowser窗口中的两个输入字段一个值,然后等待用户单击登录按钮。在此之后,我希望程序在屏幕内容为“欢迎!”(登录后包含)时打破循环 但现在的问题是:当用户名和密码的值被设置时,do循环立即开始。因此,即使我点击登录按钮,循环仍然包含点击按钮之前的网页内容,它将永远循环 我怎样才能解决这个问题?到目前为止,我考虑了两种方法: 单击按钮后重新阅读html代码,使“欢迎!”出现在代码中,然后循环将中断,或者 等待用户按下登录按钮 但在这两方面我都不知道如何解决它 WebB

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

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

我怎样才能解决这个问题?到目前为止,我考虑了两种方法:

  • 单击按钮后重新阅读html代码,使“欢迎!”出现在代码中,然后循环将中断,或者
  • 等待用户按下登录按钮
  • 但在这两方面我都不知道如何解决它

    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代码放入消息框时,我注意到了这个问题。它只是包含了“旧”代码


    提前感谢

    WinForms的金科玉律是:永远不要使用
    Application.DoEvents()
    来保持用户界面的响应性!如果您需要使用它,那么您几乎总是做错事(请参阅:)

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

    但是在这种情况下,甚至不需要循环。
    WebBrowser
    具有一个在每次完全加载页面(或页面内部的
    iframe
    )时都会引发的。使用它来知道何时执行代码

    话虽如此,下面是如何将其迁移到
    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.
    
    下面是一个小测试项目:


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

    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.
    

    或者 …如果您认为到处都有lambda太麻烦,您可以使用常规方法:

    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
    

    WinForms的金科玉律是:永远不要使用
    Application.DoEvents()
    来保持用户界面的响应性!如果您需要使用它,那么您几乎总是做错事(请参阅:)

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

    但是在这种情况下,甚至不需要循环。
    WebBrowser
    具有一个在每次完全加载页面(或页面内部的
    iframe
    )时都会引发的。使用它来知道何时执行代码

    话虽如此,下面是如何将其迁移到
    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.
    
    下面是一个小测试项目:


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

    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.
    

    或者 …如果您认为到处都有lambda太麻烦,您可以使用常规方法:

    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
    

    我试过了,但现在程序跳过了整个代码块。我在“放置代码”行中添加了一个MsgBox,但它没有显示出来。@neverlucky:这很奇怪。。。让我过一会儿再试试,我是从手机上写的。@neverlucky:按登录按钮后,页面是否真的会将您重定向到其他地方?@neverlucky:您能用更多的代码更新这个问题吗?它对我来说完全正常。@neverlucky:在页面加载完成之前,您正在关闭
    webbrowser窗口。您必须将
    WebBrowserWindow.Close()
    Me.Close()
    调用移动到与消息框相同的位置。我尝试过,但现在程序跳过了整个代码块。我在“放置代码”行中添加了一个MsgBox,但它没有显示出来。@neverlucky:这很奇怪。。。让我过一会儿再试试,我是从手机上写的。@neverlucky:按登录按钮后,页面是否真的会将您重定向到其他地方?@neverlucky:您能用更多的代码更新这个问题吗?它对我来说完全正常。@neverlucky:在页面加载完成之前,您正在关闭
    webbrowser窗口。您必须将
    WebBrowserWindow.Close()
    Me.Close()
    调用移动到与消息框相同的位置。