Je jouais avec la méthode qui a été suggérée comme une réponse à une autre de mes questions (Automate website log-in and form filling?), et j'ai remarqué quelque chose de curieux.InvalidCastException avec WebBrowser.IsBusy ou ReadyState (VB .NET)
La réponse à la question ci-dessus consistait à utiliser une série d'appels javascript comme URL afin de remplir un formulaire Web et de le soumettre. J'ai essayé de le faire automatiquement dans un programme VB .NET sans succès.
L'exemple d'origine m'a donné ne fonctionne pas, sans doute parce que vous êtes en attente sur le même fil que celui dans lequel le contrôle WebBrowser fonctionne:
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
Si vous n'attendez pas du tout, ça ne marche pas non plus, bien sûr. L'URL à laquelle vous avez accédé à l'origine est interrompue. Mais, chose intéressante, vous ne pouvez pas non plus effectuer les "navigations" des appels javascript.
J'ai donc essayé deux autres méthodes: utiliser l'événement DocumentCompleted pour attendre que l'explorateur ait fini de charger la page. Malheureusement, DocumentCompleted ne se déclenche pas toujours et ne semble pas se déclencher après chaque URL javascript.
La deuxième méthode que j'ai essayé était de mettre l'attente dans un thread séparé:
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
La chose curieuse est que le chèque de ReadyState (ou IsBusy, pour cette matière) dans la boucle d'attente va parfois jeter une InvalidCastException. Probablement les appels à ceux-ci ne sont pas thread safe? Je n'ai aucune idée. Si je mets l'appel incriminé dans un bloc Try, la boucle d'attente ne fonctionne pas. En fait, il semble même que l'exception "persiste" à tout bousiller, car même en traversant le code avec le bloc try, Visual Studio se fige pendant 10 à 20 secondes (il fait la même chose sans le bloc try).
Des idées?