C# Webbrowser 以编程方式关闭 JS 确认框

C# Webbrowser Programmatically Close JS Confirm Box

在使用网络浏览器控件时,我需要以编程方式自动关闭 javascript 确认框。

我使用了下面的 user32.dll 方法,它在基于英语的 OS 上运行良好。

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

但是如果计算机 运行 宁非英语 OS,它不能正常工作,因为我在上面的方法调用中使用 "OK" 作为文本。

我认为可行的一种方法是我应该检测 OS 语言,然后使用翻译的 "OK" 文本来使用上述方法。 这里我的问题是我可以更改当前线程的语言和 webbrowser 控件,以便它以英语显示确认框吗?在我看来,这种方式将是简单快捷的解决方案。

请提出您的解决方案。提前致谢。

我在我的代码中使用了类似的方法,但是这些解决方案仅适用于英语软件。我实际上正在寻找一些通用的解决方案,它也可以 运行 在非英语 OS 上。

一个可能的解决方案是注入并立即调用劫持原始确认函数的Javascript函数:

function hijackConfirm(){
    alert('yep!');
    window.oldConfirm = window.confirm;
    window.confirm = function(){ return true };
}

这是带有标准 WPF WebBrowser 控件的 WPF 应用程序示例,我非常有信心可以调整我在这里所做的一切以适应 WinForm 控件(因为底层 ActiveX 是相同的)。 我有一个用作 WebBrowser 适配器的 UserControl,这里是 XAML:

<UserControl x:Class="WebBrowserExample.WebBrowserAdapter"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <WebBrowser x:Name="WebBrowserControl"></WebBrowser>
    </Grid>
</UserControl>

首先,在WebBrowserAdapterclass中,你需要一个方法在当前HTML文档中注入一个javascript函数:

public void InjectScript(String scriptText)
        {
            HTMLDocument htmlDocument = (HTMLDocument)WebBrowserControl.Document;

            var headElements = htmlDocument.getElementsByTagName("head");
            if (headElements.length == 0)
            {
                throw new IndexOutOfRangeException("No element with tag 'head' has been found in the document");
            }
            var headElement = headElements.item(0);

            IHTMLScriptElement script = (IHTMLScriptElement)htmlDocument.createElement("script");
            script.text = scriptText;
            headElement.AppendChild(script);
        }

然后您在需要时调用 InjectScript,每当文档完成加载时:

void WebBrowserAdapter_Loaded(object sender, RoutedEventArgs e)
        {
            WebBrowserControl.LoadCompleted += WebBrowserControl_LoadCompleted;
            WebBrowserControl.Navigate("http://localhost:9080/console/page.html");
        }

        void WebBrowserControl_LoadCompleted(object sender, NavigationEventArgs e)
        {
            //HookHTMLElements();
            String script = 
@" function hijackConfirm(){
    alert('yep!');
    window.oldConfirm = window.confirm;
    window.confirm = function(){ return true };
}";
            InjectScript(script);
            WebBrowserControl.InvokeScript("hijackConfirm");
        }

我在这里导航到 http://localhost:9080/console/page.html,这是我系统上托管的测试页面。这在这个简单的场景中效果很好。如果您发现这适用于您,您可能需要稍微调整一下代码。为了编译代码,您必须在项目引用

中添加Microsoft.mshtml

编辑:WinForm 版本

要使其正常工作,您必须在应用程序中使用 IE 11 引擎。按照找到的说明 here 进行设置

我刚刚尝试了它的一个 WinForm 版本,它经过一些小的改动就可以工作。以下是将 WebBrowser 控件作为其子控件之一的窗体的代码:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.Load += Form1_Load;
        }

        void Form1_Load(object sender, EventArgs e)
        {
            webBrowserControl.Navigate("file:///C:/Temp/page.html");
            webBrowserControl.Navigated += webBrowserControl_Navigated;
        }

        void webBrowserControl_Navigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            InjectConfirmHijack();
        }

        private void InjectConfirmHijack()
        {
            String script =
@" function hijackConfirm(){
    alert('yep!');
    window.oldConfirm = window.confirm;
    window.confirm = function(){ return true };
}";
            InjectScript(script);
            webBrowserControl.Document.InvokeScript("hijackConfirm");
        }

        public void InjectScript(String scriptText)
        {
            //mshtml.HTMLDocument htmlDocument = (mshtml.IHTMLDocument) webBrowserControl.Document.get;

            var headElements = webBrowserControl.Document.GetElementsByTagName("head");
            if (headElements.Count == 0)
            {
                throw new IndexOutOfRangeException("No element with tag 'head' has been found in the document");
            }
            var headElement = headElements[0];

            var script = webBrowserControl.Document.CreateElement("script");
            script.InnerHtml = scriptText;
            headElement.AppendChild(script);
        }
    }