在我的程序中,我想在webbrowser窗口中为2个输入字段赋值,然后等待用户单击登录按钮。在此之后,我希望程序在屏幕内容和#34;欢迎时打破循环!" (登录后包含的内容)。
但现在问题是:当设置了用户名和密码的值时,do-loop立即启动。因此,即使我单击登录按钮,循环仍然包含单击按钮之前的网页内容,它将永远循环。
我该如何解决这个问题?到目前为止,我想过两种方法:
但在这两方面我都不知道如何解决它。
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代码放在消息框中时,我注意到了这个问题。它只包含了旧的'代码。
提前致谢
答案 0 :(得分:2)
WinForms的黄金法则是: 永远,永远 使用Application.DoEvents()
来保持您的UI响应!如果你需要使用它,那么你几乎总是做错了(参见:Keeping your UI Responsive and the Dangers of Application.DoEvents)。
不应该在UI线程上进行繁重的操作,而是在后台线程中。有多种方法可以完成UI的工作,例如Tasks,Threads或使用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