How can I confirm script error dialog box into WebBrowser?

前端 未结 1 1919
悲&欢浪女
悲&欢浪女 2021-01-14 00:28

I need to confirm programatically (i.e, answer \'yes\') to a script error dialog box into WebBrowser otherwise the page will stop working. I have no code to show because I h

相关标签:
1条回答
  • 2021-01-14 01:19

    According to the "How to handle script errors as a WebBrowser control host" MSKB article, you need to handle CGID_DocHostCommandHandler/OLECMDID_SHOWSCRIPTERROR command in the WebBrowser host.

    With a bit of coding, here is how it can be done for the WinForms WebBrowser version, and it actually works:

    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public class WebBrowserEx: WebBrowser
        {
            class WebBrowserSiteEx : WebBrowserSite, NativeMethods.IOleCommandTarget
            {
                public WebBrowserSiteEx(WebBrowser browser): base(browser)
                {
                }
    
                public int QueryStatus(IntPtr pguidCmdGroup, uint cCmds, NativeMethods.OLECMD[] prgCmds, ref NativeMethods.OLECMDTEXT CmdText)
                {
                    return NativeMethods.OLECMDERR_E_UNKNOWNGROUP;
                }
    
                public int Exec(IntPtr pguidCmdGroup, uint nCmdId, uint nCmdExecOpt, IntPtr pvaIn, IntPtr pvaOut)
                {
                    if (pguidCmdGroup != IntPtr.Zero)
                    {
                        Guid guid = (Guid)Marshal.PtrToStructure(pguidCmdGroup, typeof(Guid));
                        if (guid == NativeMethods.CGID_DocHostCommandHandler)
                        {
                            if (nCmdId == NativeMethods.OLECMDID_SHOWSCRIPTERROR)
                            {
                                // if DOM needed: dynamic document = Marshal.GetObjectForNativeVariant(pvaIn);
    
                                // continue running scripts
                                if (pvaOut != IntPtr.Zero)
                                    Marshal.GetNativeVariantForObject(true, pvaOut); 
    
                                return NativeMethods.S_OK; 
                            }
                        }
                    }
                    return NativeMethods.OLECMDERR_E_UNKNOWNGROUP;
                }
            }
    
            protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
            {
                return new WebBrowserSiteEx(this);
            }
        }
    
        public partial class Form1 : Form
        {
            WebBrowserEx _browser;
            public Form1()
            {
                InitializeComponent();
                _browser = new WebBrowserEx();
                _browser.Dock = DockStyle.Fill;
                this.Controls.Add(_browser);
    
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                // testing
                _browser.DocumentText = "<script>alert(bad.bad)</script>";
            }
        }
    
        static class NativeMethods
        {
            [StructLayout(LayoutKind.Sequential)]
            public struct OLECMD
            {
                public uint cmdID;
                public uint cmdf;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct OLECMDTEXT
            {
                public UInt32 cmdtextf;
                public UInt32 cwActual;
                public UInt32 cwBuf;
                public char rgwz;
            }
    
            public const int OLECMDERR_E_UNKNOWNGROUP = unchecked((int)0x80040102);
            public const int OLECMDID_SHOWSCRIPTERROR = 40;
            public static readonly Guid CGID_DocHostCommandHandler = new Guid("f38bc242-b950-11d1-8918-00c04fc2c836");
            public const int S_OK = 0;
    
            [ComImport, Guid("b722bccb-4e68-101b-a2bc-00aa00404770"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            public interface IOleCommandTarget
            {
                [PreserveSig]
                int QueryStatus(
                    IntPtr pguidCmdGroup,
                    UInt32 cCmds,
                    [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] OLECMD[] prgCmds,
                    ref OLECMDTEXT CmdText);
    
                [PreserveSig]
                int Exec(
                    IntPtr pguidCmdGroup,
                    uint nCmdId,
                    uint nCmdExecOpt,
                    IntPtr pvaIn,
                    IntPtr pvaOut);
            }
        }
    }
    


    Updated to address the comment:

    I need to capture the JavaScript error info in order to log it while still not displaying it to the user. I looked at the document object (the commented out line) and didn't see anything there. Is there an easy way to capture this info?

    Check the article I linked at the beginning. There are special properties errorLine, errorCharacter, errorCode, errorMessage, errorUrl available on document.parentWindow.event object.

    0 讨论(0)
提交回复
热议问题