重读浏览器窗口的内容/等待用户输入 [英] reread content of webbrowser window/wait for user input

查看:27
本文介绍了重读浏览器窗口的内容/等待用户输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的程序中,我想为 webbrowser-window 中的 2 个输入字段提供一个值,然后等待用户单击登录按钮.在此之后,我希望程序在屏幕内容欢迎!"时跳出循环.(它在登录后包含).

In my program I want to give 2 input-fields within a webbrowser-window a value and then wait for the user to click a login button. After this, I want the program to break out of the loop when the screen contents "Welcome!" (which it contains after logging in).

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

But now the problem: When the values for username and password are set, the do-loop starts instantly. So even if I click the login-button, the loop still contains the content of the webpage before the button was clicked and it will loop forever.

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

How can I solve this? I thought about two ways so far:

  1. 点击按钮后重新阅读 html 代码,以便欢迎!"将在代码内部,然后循环将中断,或者
  2. 等待用户按下登录按钮.

但在这两种方式中,我都不知道如何解决它.

But in both ways I have no real idea how to solve it.

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

I noticed the problem when I tried to put the html code in a message box. It just contained the 'old' code.

提前致谢

推荐答案

WinForms 的黄金法则是:NEVER, EVER 使用 Application.DoEvents() 让你的 UI 保持响应!如果您需要使用它,那么您几乎总是在做错事(请参阅:保持 UI 响应和应用程序的危险.DoEvents).

The golden rule of WinForms is: NEVER, EVER use Application.DoEvents() to keep your UI responsive! If you need to use it then you are almost always doing something wrong (see: Keeping your UI Responsive and the Dangers of Application.DoEvents).

繁重的操作不应该在 UI 线程上完成,而应该在后台线程中完成.有多种方式来处理 UI 的工作,例如 任务线程 或使用 BackgroundWorker.

Heavy operations should never be done on the UI thread, but in a background thread. There are multiple ways of taking the work of the UI, for instance Tasks, Threads or using the BackgroundWorker.

但是在这种情况下,您甚至不需要循环.WebBrowser 有一个 DocumentCompleted 事件 每次页面(或页面内的 iframe) 已完全加载.使用它来了解何时执行您的代码.

HOWEVER in this case, you don't even need a loop. The WebBrowser has got a DocumentCompleted event that is raised every time a page (or an iframe inside the page) has loaded completely. Use that to know when to execute your code.

话虽如此,以下是您将其迁移到 DocumentCompleted 的方法:

Having that said, here's how you'd migrate it to 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

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

Ultimately, your entire code can be changed to:

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 太麻烦,您可以退回到使用常规方法:


Alternatively

...if you think it's too messy having lambdas everywhere, you can fall back to using regular methods:

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

这篇关于重读浏览器窗口的内容/等待用户输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆