2009-12-16 22 views
2

我一直玩的方法,被建議作爲我的另一個問題的答案(Automate website log-in and form filling?),並注意到一些好奇。InvalidCastException與WebBrowser.IsBusy或ReadyState(VB.NET)

上述問題的答案是使用一系列JavaScript調用作爲URL來填寫Web表單並提交它。我一直試圖在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並不總是觸發,並且在每個JavaScript URL之後似乎都不會觸發。

我試過的第二種方法是把等待在一個單獨的線程:

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塊也是這樣)。

任何想法?

回答

1

msdn文章:「有一個控制四種方法是線程安全調用:調用,BeginInvoke的,EndInvoke會和的createGraphics和InvokeRequired屬性」

因此在子等待來電WebBrowser1.ReadyState不是線程安全

3

一個我經歷了和這對我 無法找到INET的解決方案中最有趣的問題 - 是關係到 WebBrowser控件的問題。事情是,當我試圖訪問WebBrowser控件實例的 Document屬性時,我得到 「無效的轉換異常」。事情是WebBrowser控件是設計爲在一個線程中工作的 。所以要解決這個問題,你只能檢查 InvokeRequired屬性,如果它的值爲true,那麼調用邏輯 從委託給出browser.Invoke(...)方法。

Source