Vb.net webbrowser自动导航事件

Vb.net webbrowser自动导航事件,vb.net,webbrowser-control,Vb.net,Webbrowser Control,我使用webbrowser导航到一个网站,然后自动登录。在输入一个凭证并导航到另一个网站后,在注释“导航事件”出现之前,一切都可以正常工作。事件发生后,所有代码都将不起作用,因为它不会拾取新站点。我正在使用waitforpageload()函数让我知道它何时完成加载,但是当我检查url时,它仍然指向原始站点。你知道为什么它会这样做,以及如何绕过它吗 Private Property pageready As Boolean = False webBrowser1.Navigat

我使用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

看在上帝的份上,请去掉
waitforpageload()
函数
!使用
Application.DoEvents()
是一种糟糕的做法,在这样的循环中,将使用100%的CPU

最初编写该函数的人(来自另一篇堆栈溢出帖子)显然不知道他/她当时在做什么。使用
Application.DoEvents()
所产生的问题比它所解决的问题要多,因此任何人的代码中都不应该使用(它的存在主要是因为它被内部方法使用)

有关更多信息,请参阅

WebBrowser
有一个专用的浏览器,每当一个页面(或页面的一部分,如iframe)完全加载时,该浏览器就会启动

要确保页面确实已完全加载,请订阅
DocumentCompleted
事件,并检查是否等于
WebBrowserReadyState.Complete

为了能够在引发
DocumentCompleted
事件时更“动态”地运行代码,您可以将其用作创建内联方法的一种方式

在您的情况下,它们可以这样使用:

'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")

看在上帝的份上,请去掉
waitforpageload()
函数
!使用
Application.DoEvents()
是一种糟糕的做法,在这样的循环中,将使用100%的CPU

最初编写该函数的人(来自另一篇堆栈溢出帖子)显然不知道他/她当时在做什么。使用
Application.DoEvents()
所产生的问题比它所解决的问题要多,因此任何人的代码中都不应该使用(它的存在主要是因为它被内部方法使用)

有关更多信息,请参阅

WebBrowser
有一个专用的浏览器,每当一个页面(或页面的一部分,如iframe)完全加载时,该浏览器就会启动

要确保页面确实已完全加载,请订阅
DocumentCompleted
事件,并检查是否等于
WebBrowserReadyState.Complete

为了能够在引发
DocumentCompleted
事件时更“动态”地运行代码,您可以将其用作创建内联方法的一种方式

在您的情况下,它们可以这样使用:

'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")

首先,您有太多的
waitforpageload()
方法调用。设置元素属性时无需等待任何操作。然后,需要考虑的是:您是否只需要为这两个站点执行此操作?如果是这样,您只需要为
DocumentComplete()
提供一个事件处理程序。设置一个逻辑来区分站点,可能使用它们的页面标题(或其他元素),并相应地采取行动。@Jimi第二个页面有一个新的URL,但当我在处理第一个页面后导航到它时,它会将我踢出。将导航视为新页面。此外,我还更新了waitforpagetoload()方法调用。我将研究如何利用页面标题或其他元素。@Jimi(和Cole):第三件事,不要使用
waitforpageload()
@科尔·佩罗特“把我踢出去”还没有定义。接下来的一段时间:(1)导航第一个URL(…导航…=>
DocumentComplete()
fired=>(2)设置登录值->调用成员()=>login accepted=>(…导航…=>
DocumentComplete()
fired(3)登录页面->新登录表单->设置值->调用成员=>login accepted=>(…导航…=>
DocumentComplete())
(4)登录页面->在此处执行任何需要执行的操作首先,您有太多的
waitforpageload()
方法调用。设置元素属性时无需等待任何操作。然后,需要考虑的是:您是否只需要为这两个站点执行此操作?如果是这样,您只需要为
DocumentComplete()
提供一个事件处理程序。设置一个逻辑来区分站点,可能使用它们的页面标题(或其他元素),并相应地采取行动。@Jimi第二个页面有一个新的URL,但当我在处理第一个页面后导航到它时,它会将我踢出。将导航视为新页面。此外,我还更新了waitforpagetoload()方法调用。我将研究如何利用页面标题或其他元素。@Jimi(和Cole):第三件事,不要使用
waitforpageload()
@科尔·佩罗特“把我踢出去”还没有定义。接下来的一段时间:(1)导航第一个URL(…导航…=>
DocumentComplete()
fired=>(2)设置登录值->调用成员()=>login accepted=>(…导航…=>
DocumentComplete()
fired(3)登录页面->新登录表单->设置值->调用成员=>login accepted=>(…导航…=>
DocumentComplete())
(4)登陆页面->在这里做任何你需要做的事情非常感谢你的解释,代码工作得非常好!但是,我有一个页面,我必须从下拉菜单中选择项目,然后显示某些文本框。你知道我该如何捕捉这些信息吗?@ColePerrault:如果我的答案解决了你的问题,请按我帖子左侧的勾号/复选标记,将其标记为已接受。@ColePerrault:至于你的另一个请求(在这个问题中与主题无关):在页面中插入一些Javascript,以响应下拉列表的,然后调用一个外部VB.NET方法。下面是一个从JS调用.NET方法的示例(在C#bu中)