由於項目需求,最近轉戰客戶端,開始搞瀏覽器開發。眾所周知,現在在微軟平台上開發瀏覽器,最常用的方法就是擴展Webbrowser,但是首先要清楚的是,WebBrowser控件僅僅是對WebBrowser ActiveX 控件提供了托管包裝而已(詳細了解http://msdn.microsoft.com/zh-cn/library/w290k23d(VS.80).aspx),要寫一個像點樣子的瀏覽器,很多方面還是要自己去擴展的,否則開發出來的也只能是個樣子,沒多少實際功能。 本篇隨筆重點將介紹如何處理WebBrowser對JS的錯誤處理問題。 可能有些朋友看到上句話會覺得,這問題不是很簡單嘛,設置一下 ScriptErrorsSuppressed屬性不就完了嘛,殊不知這樣做,像其他的譬如網頁安全驗證的彈出框,甚至很多其他網頁內部彈出窗口也都被禁止掉了,如此當然是行不通的。可能還會有一部分朋友會說,那可以通過WebBrowser向網頁中注入JS錯誤處理腳本,捕獲JS錯誤,不是也可以嘛。那我會告訴你,這種方法在面對使用很多iframe的網站是也玩完。 那么接下來,我將介紹,如何更好的避免WebBrowser中的JS錯誤。 避免錯誤,首先要想到辦法去捕獲錯誤,查遍了網上的很多資料,發現是要去實現IOleCommandTarget接口,調用接口中的Exec方法來捕獲異常,然后解決,當然如果需要去調用IE的一些功能,也得需實現IObjectWithSite接口。 定義IOleCommandTarget接口、OLECMD類: public static class NativeMethods { public enum OLECMDF { // Fields OLECMDF_DEFHIDEONCTXTMENU = 0x20, OLECMDF_ENABLED = 2, OLECMDF_INVISIBLE = 0x10, OLECMDF_LATCHED = 4, OLECMDF_NINCHED = 8, OLECMDF_SUPPORTED = 1 } public enum OLECMDID { // Fields OLECMDID_PAGESETUP = 8, OLECMDID_PRINT = 6, OLECMDID_PRINTPREVIEW = 7, OLECMDID_PROPERTIES = 10, OLECMDID_SAVEAS = 4, OLECMDID_SHOWSCRIPTERROR = 40 } public enum OLECMDEXECOPT { // Fields OLECMDEXECOPT_DODEFAULT = 0, OLECMDEXECOPT_DONTPROMPTUSER = 2, OLECMDEXECOPT_PROMPTUSER = 1, OLECMDEXECOPT_SHOWHELP = 3 } [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B722BCCB-4E68-101B-A2BC-00AA00404770"), ComVisible(true)] public interface IOleCommandTarget { [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int QueryStatus(ref Guid pguidCmdGroup, int cCmds, [In, Out] NativeMethods.OLECMD prgCmds, [In, Out] IntPtr pCmdText); [return: MarshalAs(UnmanagedType.I4)] [PreserveSig] int Exec(ref Guid pguidCmdGroup, int nCmdID, int nCmdexecopt, [In, MarshalAs(UnmanagedType.LPArray)] object[] pvaIn, ref int pvaOut); } [StructLayout(LayoutKind.Sequential)] public class OLECMD { [MarshalAs(UnmanagedType.U4)] public int cmdID; [MarshalAs(UnmanagedType.U4)] public int cmdf; public OLECMD() { } } public const int S_FALSE = 1; public const int S_OK = 0; public static readonly Guid CGID_DocHostCommandHandler = new Guid("f38bc242-b950-11d1-8918-00c04fc2c836"); public const int VARIANT_TRUE = -1; public const int VARIANT_FALSE = 0; public const int OLECMDERR_E_NOTSUPPORTED = -2147221244; } 然后定義一個類ExtendedWebBrowserSite,去實現接口: class ExtendedWebBrowserSite : WebBrowserSite, NativeMethods.IOleCommandTarget { /// <summary> /// Creates a new instance of the <see cref="ExtendedWebBrowserSite"/> class /// </summary> /// <param name="host">The <see cref="ExtendedWebBrowser"/> hosting the browser</param> public ExtendedWebBrowserSite(ExtendedWebBrowser host) : base(host) { _host = host; } private ExtendedWebBrowser _host; private ExtendedWebBrowser Host { get { return _host; } } #region IOleCommandTarget Members int NativeMethods.IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, int cCmds, NativeMethods.OLECMD prgCmds, IntPtr pCmdText) { return NativeMethods.S_FALSE; } int NativeMethods.IOleCommandTarget.Exec(ref Guid pguidCmdGroup, int nCmdID, int nCmdexecopt, object[] pvaIn, ref int pvaOut) { int hResult = NativeMethods.S_OK; if (pguidCmdGroup == null) return hResult; // Check for invalid pointers (or get a NullReferenceException on a value type???) //if (NativeMethods.CGID_DocHostCommandHandler.Equals(pguidCmdGroup)) { switch (nCmdID) { case (int)NativeMethods.OLECMDID.OLECMDID_SHOWSCRIPTERROR: // Hide the dialog pvaOut = NativeMethods.VARIANT_TRUE; break; default: hResult = NativeMethods.OLECMDERR_E_NOTSUPPORTED; break; } } return hResult; } #endregion } } 當然這里主要是通過實現IOleCommandTarget.Exec方法去捕獲OLECMDID.OLECMDID_SHOWSCRIPTERROR消息,然后避免異常。 最后在你的擴展的WebBrowser里面重載一下CreateWebBrowserSiteBase方法,完成調用。 protected override WebBrowserSiteBase CreateWebBrowserSiteBase() { return new ExtendedWebBrowserSite(this); }
原文:http://blog.csdn.net/tangyanzhi1111/article/details/8990459
