Я играл с методом, предложенным в качестве ответа на другой мой вопрос ( Автоматизировать вход на сайт и заполнять форму? ), и заметил кое-что любопытное.
Ответом на вышеупомянутый вопрос было использование серии вызовов javascript в качестве URL-адресов для заполнения веб-формы и ее отправки. Я пытался сделать это автоматически в программе VB .NET безуспешно.
Исходный пример, который я привел, не работает, вероятно, потому, что вы ожидаете в том же потоке, в котором работает элемент управления 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
Если вы вообще не ждете, это тоже не сработает. URL-адрес, по которому вы первоначально просматриваете, прерван. Но, что интересно, вы также не можете выполнить «навигацию» к вызовам javascript без задержки.
Итак, я попробовал два других метода: использовать событие DocumentCompleted, чтобы дождаться просмотра URL-адреса гнезда, пока браузер не завершит загрузку страницы. К сожалению, DocumentCompleted не всегда срабатывает и, похоже, не срабатывает после каждого URL-адреса JavaScript.
Второй метод, который я попробовал, состоял в том, чтобы поместить ожидание в отдельный поток:
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
Любопытно, что проверка ReadyState (или IsBusy, в этом отношении) в цикле ожидания иногда вызывает исключение InvalidCastException. Предположительно, звонки на них не безопасны? Я понятия не имею. Если я помещаю вызывающий вызов вызов в блок Try, цикл ожидания просто не работает. На самом деле, даже кажется, что исключение «сохраняется», чтобы все испортить, потому что даже при пошаговом выполнении кода с блоком try Visual Studio останавливается на добрые 10–20 секунд (то же самое происходит и без блока try).
Есть идеи?