浏览器自动导航事件 [英] webbrowser auto navigation event
问题描述
我正在使用 webbrowser 导航到一个网站,然后自动登录.一切正常,直到评论导航事件" 输入一个凭据后,它将登录并导航到另一个网站.事件发生后,所有代码都不会工作,因为它没有选择新站点.我正在使用 waitforpageload() 函数来让我知道它何时完成加载,但是当我检查 url 时,它仍然指向原始站点.任何想法为什么会这样做以及如何解决它?
I am using webbrowser to navigate to a website then automating the login. Everything works perfectly up until the point of the comment "Navigating Event" After entering one credential it will login and navigate to another website. After the event none of the code will work as it is not picking up the new site. I am using a waitforpageload() function to let me know when it is completed loading however when I check the url it is still pointing to the original site. Any ideas why it would be doing this and how to possibly get around it?
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
推荐答案
拜托,看在上帝的份上,去掉那个waitforpageload()
函数!使用 Application.DoEvents()
是不良做法,在这样的循环中,将 100% 使用 CPU!
Please, for the love of god, get rid of that waitforpageload()
function! Using Application.DoEvents()
is BAD PRACTICE and in a loop like that, will utilize 100% of your CPU!
最初编写该函数的人(来自另一篇 Stack Overflow 帖子)显然不知道他/她当时在做什么.使用 Application.DoEvents()
会产生比它解决的更多的问题,并且应该永远在任何人的代码中使用(它存在主要是因为它被使用通过内部方法).
The person who originally wrote that function (it's from another Stack Overflow post) clearly didn't know what he/she was doing at the time. Using Application.DoEvents()
creates more problems than it solves, and should NEVER be used in anyone's code (it exists mostly because it is used by internal methods).
参考:保持 UI 响应性和 Application.DoEvents 的危险了解更多信息.
Refer to: Keeping your UI Responsive and the Dangers of Application.DoEvents for more info.
WebBrowser
有一个专用的 DocumentCompleted
事件 每次页面(或页面的一部分,例如 iframe)完全加载时都会引发该事件.
The WebBrowser
has a dedicated DocumentCompleted
event that is raised every time a page (or part of a page, such as an iframe) has been completely loaded.
要确保页面确实已完全加载,请订阅 DocumentCompleted
事件并检查 ReadyState
属性 等于 WebBrowserReadyState.Complete代码>.
To make sure that the page really is fully loaded, subscribe to the DocumentCompleted
event and check if the ReadyState
property is equal to WebBrowserReadyState.Complete
.
为了能够在引发 DocumentCompleted
事件时更动态地"运行代码,您可以使用 lambda 表达式 作为创建内联方法的一种方式.
To be able to run code more "dynamically" when the DocumentCompleted
event is raised you can utilize lambda expressions as a way of creating inline methods.
在您的情况下,它们可以这样使用:
In your case they can be used like this:
'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
中:
Now every time you need to wait for the document/website to be fully loaded, just declare a new lambda and add it as an event handler to 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
这篇关于浏览器自动导航事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!