InvalidCastException z WebBrowser.IsBusy lub ReadyState (VB .NET)

Bawiłem się metodą zaproponowaną jako odpowiedź na inne moje pytanie (Zautomatyzuj logowanie do witryny i wypełnianie formularzy?) i zauważyłem coś ciekawego.

Odpowiedzią na powyższe pytanie było użycie serii wywołań javascript jako adresów URL w celu wypełnienia formularza internetowego i przesłania go. Próbowałem to zrobić automatycznie w programie VB .NET bez powodzenia.

Oryginalny przykład, który mi podano, nie działa, prawdopodobnie dlatego, że czekasz na ten sam wątek, w którym działa formant WebBrowser:

WebBrowser1.Navigate("http://www.google.com")
Do While WebBrowser1.IsBusy OrElse WebBrowser1.ReadyState <> WebBrowserReadyState.Complete
    Threading.Thread.Sleep(1000)
Application.DoEvents()
Loop
WebBrowser1.Navigate("javascript:function%20f(){document.forms[0]['q'].value='stackoverflow';}f();")
Threading.Thread.Sleep(2000) 'wait for javascript to run
WebBrowser1.Navigate("javascript:document.forms[0].submit()")
Threading.Thread.Sleep(2000) 'wait for javascript to run

Jeśli w ogóle nie czekasz, to oczywiście nie działa. Adres URL, do którego pierwotnie przeglądasz, został przerwany. Co ciekawe, nie można również bezzwłocznie wykonywać „nawigacji” do wywołań javascript.

Próbowałem więc dwóch innych metod: za pomocą zdarzenia DocumentCompleted poczekać na przejście do adresu URL gniazda, dopóki przeglądarka nie zakończy ładowania strony. Niestety, DocumentCompleted nie zawsze uruchamia się i wydaje się, że nie uruchamia się po każdym javascriptowym URL.

Drugą metodą, którą próbowałem, było umieszczenie oczekiwania w osobnym wątku:

 Private Delegate Sub SetTextDelegate(ByVal TheText As String)
 Private Sub delSetText(ByVal TheText As String)
     WebBrowser1.Navigate(TheText)
 End Sub

 Private Sub BrowseTo(ByVal URL As String)
     If WebBrowser1.InvokeRequired Then
         Me.BeginInvoke(New SetTextDelegate(AddressOf delSetText), URL)
     Else
         WebBrowser1.Navigate(URL)
     End If
 End Sub

 Private Sub TargetURL()
   BrowseTo("http://www.google.com")
 End Sub

 Private Sub TypeSomethingIn()
     BrowseTo("javascript:function%20f(){document.forms[0]['g'].value='test';}f();")
 End Sub

 Private Sub SubmitForm()
     BrowseTo("javascript:document.forms[0].submit()")
 End Sub

 Private Sub Wait()
     While True
         If WebBrowser1.ReadyState = WebBrowserReadyState.Complete Then Exit Sub
         Threading.Thread.Sleep(100)
     End While
 End Sub

 Private Sub AutoBrowse()
     TargetURL()
     Wait()
     TypeSomethingIn()
     Wait()
     SubmitForm()
 End Sub

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     Dim t As Threading.Thread
     t = New Threading.Thread(AddressOf AutoBrowse)
     t.Start()
 End Sub

Ciekawostką jest to, że sprawdzenie ReadyState (lub IsBusy, o to chodzi) w pętli wait czasami rzuca wyjątek InvalidCastException. Przypuszczalnie połączenia z tymi nie są bezpieczne dla wątków? Nie mam pojęcia. Jeśli umieściłem obraźliwe wywołanie w bloku Try, pętla oczekiwania nie działa. W rzeczywistości wydaje się, że wyjątek „utrzymuje się”, aby wszystko spieprzyć, ponieważ nawet przejście przez kod przy pomocy bloku próbnego Visual Studio zawiesza się na dobre 10 do 20 sekund (robi to samo bez bloku try).

Jakieś pomysły?

questionAnswers(2)

yourAnswerToTheQuestion