1

while using webbrowser control, I need to programmatically auto close a javascript confirm box.

I used below user32.dll approach and it is working fine on OS which are based english language.

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

But if the computer running non-english OS, it is not working fine as I am using "OK" as text in above method call.

One approach which I suppose can work is I should detect OS language and then use translated "OK" text to use above method. Here my question is can I change language of the current thread and so webbrowser control so that it show confirm box in English language? This way it would be easy and fast solution in my opinion.

Please suggest your solutions. Thanks in advance.

I am using similar approach in my code however these solutions are working for English language software only. I am actually looking for some generic solution that can run on non-english OS as well.

  • possible duplicate of [Force close of MessageBox](http://stackoverflow.com/questions/7926107/force-close-of-messagebox) – MethodMan Jun 26 '15 at 06:45
  • There's a possible solution here with a downloadable example. Admittedly it's in VB, but it shouldn't be too hard to convert to C# [LINK](http://vbcity.com/forums/t/105842.aspx) – Equalsk Jun 26 '15 at 08:03
  • @MethodMan, Equalsk, Please read the question again. I am using similar approach in my code however these solutions are working for English language software only. I am actually looking for some generic solution that can run on non-english OS as well. – Ashok Kumar Jun 26 '15 at 08:20
  • Apologies, I read the question but didn't realise that solution still used localised strings. You can definitely [get the OS language](http://stackoverflow.com/questions/5710127/get-operating-system-language-in-c-sharp) but I don't know how you'd get the translated text. [This](http://stackoverflow.com/questions/3455172/can-you-access-standard-windows-strings-like-cancel) post talks about accessing Windows strings, or you'd have to maintain your own dictionary. – Equalsk Jun 26 '15 at 10:09

1 Answers1

1

A possible solution consists in injecting and immediately calling a Javascript function that hijacks the original confirm function:

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

This is an example in WPF application with the standard WPF WebBrowser control, I'm quite confident that everything I do here can be adjusted to fit the WinForm control (since the underlying ActiveX is the same). I have a UserControl that acts as an adapter of the WebBrowser, here is the 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>

First, in the WebBrowserAdapter class, you need a method to inject a javascript function in the current HTML document:

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);
        }

then you call InjectScript, when needed, whenever a document completes to load:

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");
        }

Here I navigate to http://localhost:9080/console/page.html, which is a test page hosted on my system. This works well in this simple scenario. If you find this could apply to you, you may need to tweak a little bit the code. In order to compile the code, you have to add Microsoft.mshtml in the project references

EDIT: WinForm version

To make it work, you have to use the IE 11 engine in your application. Follow the instructions found here to set it

I just tried a WinForm version of this and it works with some minor changes. Here is the code of a form that has a WebBrowser control as one of its children:

    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);
        }
    }
Evil Toad
  • 3,053
  • 2
  • 19
  • 28