標籤:winform style blog http java color
原文:C# winform調用WebBrowser經典怪問題總結
最近一直研究網頁資料擷取,單單採集資料,其實HtmlAgilityPack就足夠了。
對HtmlAgilityPack感興趣的可以到這裡看看:C#採集Proxy 伺服器ip並設定IE代理--HtmlAgilityPack實戰代碼
但是有個問題:要是想要類比人工輸入資料,進行表單提交HtmlAgilityPack就辦不了,Skybound.Gecko(firfox的.net開原始碼)
也辦不了這個事情。Skybound.Gecko不支援點擊,不知道大家有沒有新的方法。
反正我只能用微軟內建的WebBrowser來類比網頁點擊了。
剛開始一切正常,但是隨著功能增加,有幾個問題就出來了。下面一一列出,並給出基本解決辦法。
1) 屏蔽指令碼錯誤對話方塊
解決辦法:
webBrowser1.ScriptErrorsSuppressed = true;//我經常設定成false。汗顏啊 。
2.屏蔽Js彈出框(能夠屏蔽conform的)
一定要寫在你提交事件之前!
IHTMLDocument2 vDocument = (IHTMLDocument2)webBrowser1.Document.DomDocument; vDocument.parentWindow.execScript("function confirm(str){return true;} ", "javascript"); //彈出確認 vDocument.parentWindow.execScript("function alert(str){return true;} ", "javaScript");//彈出提示 element.InvokeMember("click");//element是我需要的提交按鈕
3.WebBrowser的DocumentCompleted執行多次的原因(包含多個iframe造成的)
情況1、WebBrowser載入一個頁面後DocumentCompleted事件會執行兩次,
但這兩次的ReadyState狀態不一樣,分別是Intercative和Complete。
而MSDN對這兩種狀態值的解釋是:
Complete該控制項已完成新文檔及其所有內容的載入;
Interactive該控制項已經載入足夠的文檔以允許有限的使用者互動,比如單擊已顯示的超連結。
由此可見,實際上DocumentCompleted事件會在Interactive狀態和Complete狀態各調用一次,
那麼我們可以根據我們的需要來判斷到底需要那一次。解決辦法執行個體代碼如下:
if(webBrowser1.ReadyState!=WebBrowerReadyState.Complete) return;
情況2、如果一個頁面中含有多個架構頁Iframes,那麼在每個架構頁載入完成時也可能觸發一次DocumentCompleted事件
MSDN對其解釋是在多個的幀的情況下DocumentComplete擷取觸發多次。
並非每個架構將觸發此事件,但觸發DownloadBegin事件的每個架構將觸發相應的DocumentComplete事件。
這種情況下解決辦法執行個體代碼如下:
if(e.Url.ToString()!=webBrowser1.Url.ToString()) return;
4.徹底解決彈出問題:方法2中說明的代碼,解決彈出一次對話方塊的問題,如果連續彈出conform和alert就會失效。
最後終極方法:就是繼承WebBrowser,屏蔽掉彈出框事件,或者加上你自己的處理方法。
這是一個治本的方法。也不是很複雜。
建立一個類,繼承自System.Windows.Forms.WebBrowser。
直接:http://pan.baidu.com/share/link?shareid=1906864666&uk=1765114824
public class MyWebBrowser : System.Windows.Forms.WebBrowser { #region ExtendedWebBrowserSite class ExtendedWebBrowserSite : WebBrowser.WebBrowserSite, UnsafeNativeMethods.IDocHostShowUI { public ExtendedWebBrowserSite(WebBrowser host) : base(host) { } void UnsafeNativeMethods.IDocHostShowUI.ShowMessage(ref UnsafeNativeMethods._RemotableHandle hwnd, string lpstrText, string lpstrCaption, uint dwType, string lpstrHelpFile, uint dwHelpContext, out int plResult) { plResult = 0; //TODO:自訂 } void UnsafeNativeMethods.IDocHostShowUI.ShowHelp(ref UnsafeNativeMethods._RemotableHandle hwnd, string pszHelpFile, uint uCommand, uint dwData, UnsafeNativeMethods.tagPOINT ptMouse, object pDispatchObjectHit) { //TODO:自訂 } } protected override WebBrowserSiteBase CreateWebBrowserSiteBase() { return new ExtendedWebBrowserSite(this); } #endregion } public class UnsafeNativeMethods { #region IDocHostShowUI [StructLayout(LayoutKind.Explicit, Pack = 4)] public struct __MIDL_IWinTypes_0009 { // Fields [FieldOffset(0)] public int hInproc; [FieldOffset(0)] public int hRemote; } [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct _RemotableHandle { public int fContext; public __MIDL_IWinTypes_0009 u; } [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct tagPOINT { public int x; public int y; } [ComImport, Guid("C4D244B0-D43E-11CF-893B-00AA00BDCE1A"), InterfaceType((short)1)] public interface IDocHostShowUI { [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] void ShowMessage([In, ComAliasName("ExtendedWebBrowser2.UnsafeNativeMethods.wireHWND")] ref _RemotableHandle hwnd, [In, MarshalAs(UnmanagedType.LPWStr)] string lpstrText, [In, MarshalAs(UnmanagedType.LPWStr)] string lpstrCaption, [In] uint dwType, [In, MarshalAs(UnmanagedType.LPWStr)] string lpstrHelpFile, [In] uint dwHelpContext, [ComAliasName("ExtendedWebBrowser2.UnsafeNativeMethods.LONG_PTR")] out int plResult); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] void ShowHelp([In, ComAliasName("ExtendedWebBrowser2.UnsafeNativeMethods.wireHWND")] ref _RemotableHandle hwnd, [In, MarshalAs(UnmanagedType.LPWStr)] string pszHelpFile, [In] uint uCommand, [In] uint dwData, [In] tagPOINT ptMouse, [Out, MarshalAs(UnmanagedType.IDispatch)] object pDispatchObjectHit); } #endregion }
View Code
WebBrowser說實話潛規則太多,沒辦法才用他。苦逼啊。
如果對你有協助,請點擊推薦哦。