我正在使用webbrowser导航到一个网站,然后自动登录。一切都完美无缺,直到评论“导航事件”为止。输入一个凭证后,它将登录并导航到另一个网站。事件发生后,没有任何代码可以正常工作,因为它没有拿起新网站。我正在使用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
答案 0 :(得分:2)
请为了上帝的爱, 摆脱waitforpageload()
功能 !使用Application.DoEvents()
是 BAD PRACTICE ,在这样的循环中,将使用100%的CPU!
最初编写该功能的人(来自另一个Stack Overflow帖子)显然不知道他/她当时在做什么。使用Application.DoEvents()
会产生比解决的问题更多的问题, NEVER 应该在任何人的代码中使用(它的存在主要是因为内部方法使用它)。
有关详细信息,请参阅:Keeping your UI Responsive and the Dangers of Application.DoEvents。
每次页面(或页面的一部分,例如iframe)完全加载时,WebBrowser
都会有一个专用的DocumentCompleted
event。
要确保页面确实已完全加载,请订阅DocumentCompleted
事件并检查ReadyState
property是否等于WebBrowserReadyState.Complete
。
能够更多地运行代码"动态地"引发DocumentCompleted
事件时,您可以使用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")
现在,每当您需要等待文档/网站完全加载时,只需声明一个新的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