最近寫了個軟體叫WebAutoScript,目的用於,網頁的自動操作處理,就是說,所有你在網頁上面的操作,都可以錄到一個指令碼中,然後可以回放這個操作過程。。我是說任何過程。
程式是用C#寫的,其中遇到了一個難題,對於網頁,我是用C#內建的WebBrowser控制項控制,但是這個控制項有個問題,就是不能準確判斷網頁什麼時候最終裝載完畢,如果這個不能判斷的話,我根本不可以判斷什麼時候執行下一個動作,因為網頁還沒有開啟,不可能去點擊還沒有出現的按鈕等。。。google了海內外,竟然沒有人搞定過,除非不用這個控制項,雖然有別的控制項可以,如AxWebBrowser,但是用另外的控制項,又會出現另外的問題,所以最後決定還是用內建的WebBrowser,但是怎麼解決這個難題呢。。。
為什麼這個控制項不能準確判斷網頁什麼時候裝載完畢呢,那是因為現在的網頁一般都有多個frame,一個frame相當於另一個網頁,在不斷裝載,訊息不斷的觸發,所以難以判斷觸發完成的是那個網頁。。。
網上一般都是說根據Browser_DocumentCompleted,Browser_Navigated,Browser_Navigating這三個訊息來判斷的,用什麼計數器啦,還有判斷IsBusy,StatusText等。。以上或多或少對於一些網頁是可行的,對於另一些網頁卻又有另外的意外,所以總的來說,不能通用準確。。。
總得來說,一個網頁最終裝載完畢,不管它裡面多少個frame,最終完成只有一次,也是可以提供給程式可以執行下一步操作的訊息。
怎麼解決呢,其實,WebBrowser的工作機制大概是這樣的,在url上打上www.163.com,這時候,WebBrowser會開始裝載www.163.com這個網頁,觸發一個Browser_Navigating,ReadyState置為非Complete,IsBusy置為true,StatusText置為"請求的url內容",這個文檔完畢後,觸發一個Browser_DocumentCompleted,同時,ReadyState置為Complete,IsBusy置為false,StatusText置為"完成",如果通常都會有frame,如www.163.com/kk.jsp#fsd什麼的,WebBrower就會觸發Browser_Navigating,ReadyState置為非Complete,IsBusy置為true,StatusText置為"請求的url內容",再去裝載那個frame,完畢後,觸發一個Browser_DocumentCompleted,同時,ReadyState置為Complete,IsBusy置為false,StatusText置為"完成",剩下的frame,餘次類推。
上面的過程有一個特點,從主文件到frame的過程,ReadyState置為Complete,IsBusy置為false,StatusText置為"完成",這個時間是很短的,Browser_DocumentCompleted觸發一下就過去了,如果還有frame,很快就會把狀態搞成非完成,所以根據這個特點。。。我們可以找一種方法來判斷什麼時候才是最終完成。。。
我的方法是:在WebBrowser開始裝載www.163.com這個網頁的時候,觸發Browser_Navigating的時候,我開啟一個timer,在那裡監控,Interval為200ms,如果MainBrowser的ReadyState == WebBrowserReadyState.Complete && IsBusy == false的話,證明現在有兩種情況,WebBrowser已經最終裝載完畢,或者是剛裝載完結一個,很快就會裝載另外一個frame,不管,先記錄這時候的DocumentText,DocumentTitle,DocumentTitle,Url,等到下一個200ms,timer再判斷現在的WebBrowser的ReadyState == WebBrowserReadyState.Complete && IsBusy == false,如果不成立,則把記錄的狀態清掉,那些DocumentText,現在肯定還沒有到最終完成狀態啦,但是,如果成立的話,把現在的WebBrowser的狀態和上一次timer記錄的狀態對比,如果不相等,那也只能說明還沒有到達最終狀態,如果相同,設定一個記數器,加1,就這樣,如果這個計數器最終能夠達到5次,就說明WebBrowser最終完成裝載了。。。簡單的說,就是加多一個timer來監控WebBrowser幾個重要狀態值,如果在5*200ms一秒內,其狀態沒有變化過,就證明,其已經最終裝載完畢。。。
這種方式,百試百靈,沒有遇到過誤判的情況,呵呵,強吧,MS沒有完善的地方,咱們自己想辦法唄。。。