admin管理员组

文章数量:1289565

I am using webBrowser.Document.InvokeScript("Function") to run a javascript, located in a local file opened with the Winforms WebBrowser.

The problem is, I need the javascript to finish executing before continuing. How do I wait/listen for that?

This is my C# code:

    private void Button1_ItemClick_1(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
    {
        webBrowser.Document.InvokeScript("Script_A");
        Method_A();
        DialogResult = System.Windows.Forms.DialogResult.OK;
    }

Javascript code:

<script>function Script_A() { Script_B(); }</script>

How do I make sure that Method_A is not executed before Script_B has finished?

I am using webBrowser.Document.InvokeScript("Function") to run a javascript, located in a local file opened with the Winforms WebBrowser.

The problem is, I need the javascript to finish executing before continuing. How do I wait/listen for that?

This is my C# code:

    private void Button1_ItemClick_1(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
    {
        webBrowser.Document.InvokeScript("Script_A");
        Method_A();
        DialogResult = System.Windows.Forms.DialogResult.OK;
    }

Javascript code:

<script>function Script_A() { Script_B(); }</script>

How do I make sure that Method_A is not executed before Script_B has finished?

Share Improve this question edited May 22, 2013 at 12:26 Valentin Kold Gundersen asked May 22, 2013 at 12:08 Valentin Kold GundersenValentin Kold Gundersen 451 gold badge2 silver badges5 bronze badges 1
  • 1 You could make the JavaScript call back to the WinForms application notifying it that the script has finished and that sets a flag that is either checked by your ButtonClick code or finishes off the button code. – Belogix Commented May 22, 2013 at 12:11
Add a ment  | 

2 Answers 2

Reset to default 8

using async/await you can wait until the script is executed without blocking the UI.

public async void AMethod()
{
    string script =
     @"<script>
        function Script_A() { 
            Script_B(); 
            window.external.Completed(); //call C#: CallbackObject's Completed method
        }
        function Script_B(){
            alert('in script');
        }
    </script>";

    TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();

    webBrowser1.ObjectForScripting = new CallbackObject(tcs);
    //Ensure DocumentText is loaded before invoking "InvokeScript",
    //by extension method "SetDocumentTextAsync" (below)
    await webBrowser1.SetDocumentTextAsync(script);
    webBrowser1.Document.InvokeScript("Script_A");

    await tcs.Task;

    MessageBox.Show("Script executed");
}


[ComVisible(true)]
public class CallbackObject
{
    TaskCompletionSource<bool> _tcs = null;

    public CallbackObject(TaskCompletionSource<bool> tcs)
    {
        _tcs = tcs;
    }
    public void Completed()
    {
        _tcs.TrySetResult(true);
    }
}

public static class BrowserExtensions
{
    public static Task SetDocumentTextAsync(this WebBrowser wb, string html)
    {
        TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
        WebBrowserDocumentCompletedEventHandler pletedEvent = null;
        pletedEvent = (sender, e) =>
        {
            wb.DocumentCompleted -= pletedEvent;
            tcs.SetResult(null);
        };
        wb.DocumentCompleted += pletedEvent;

        wb.ScriptErrorsSuppressed = true;
        wb.DocumentText = html;

        return tcs.Task;
    }
}

You would Need to implement a callback-method (don't Forget ComVisible-Attribute) which you would be calling from your script using

window.mymethod();

This way, you would actually need to 'split' your method.

Here is a nice post from SO.


And here is a tutorial:

Call a C# Method From JavaScript Hosted in a WebBrowser

By AspDotNetDev, 6 May 2011

This sample demonstrates how to call C# from JavaScript. It also shows that parameters can be passed to C# methods.

First, create a Windows Forms application. Then, add a WebBrowser control to your form. Then modify the code for the form so it looks like this:

 namespace WindowsFormsApplication6
{
    // This first namespace is required for the ComVisible attribute used on the ScriptManager class.
    using System.Runtime.InteropServices;
    using System.Windows.Forms;

    // This is your form.
    public partial class Form1 : Form
    {
        // This nested class must be ComVisible for the JavaScript to be able to call it.
        [ComVisible(true)]
        public class ScriptManager
        {
            // Variable to store the form of type Form1.
            private Form1 mForm;

            // Constructor.
            public ScriptManager(Form1 form)
            {
                // Save the form so it can be referenced later.
                mForm = form;
            }

            // This method can be called from JavaScript.
            public void MethodToCallFromScript()
            {
                // Call a method on the form.
                mForm.DoSomething();
            }

            // This method can also be called from JavaScript.
            public void AnotherMethod(string message)
            {
                MessageBox.Show(message);
            }
        }

        // This method will be called by the other method (MethodToCallFromScript) that gets called by JavaScript.
        public void DoSomething()
        {
            // Indicate success.
            MessageBox.Show("It worked!");
        }

        // Constructor.
        public Form1()
        {
            // Boilerplate code.
            InitializeComponent();

            // Set the WebBrowser to use an instance of the ScriptManager to handle method calls to C#.
            webBrowser1.ObjectForScripting = new ScriptManager(this);

            // Create the webpage.
            webBrowser1.DocumentText = @"<html>
                <head>
                    <title>Test</title>
                </head>
                <body>
                <input type=""button"" value=""Go!"" onclick=""window.external.MethodToCallFromScript();"" />
                    <br />
                    <input type=""button"" value=""Go Again!"" onclick=""window.external.AnotherMethod('Hello');"" />
                </body>
                </html>";
        }
    }
}

Note that your application may be part of a namespace other than WindowsFormsApplication6, but the rest of the code should work if you follow the above instructions explicitly. I created this tip/trick because somebody asked me a question and they didn't understand this sample that I sent them to. This tip/trick makes the sample more understandable by fixing the two bugs I spotted, adding the using statements that weren't mentioned, and by heavily menting the code. Hopefully the rest of you will find this of use as well. License

本文标签: cInvoke a script in WebBrowserand wait for it to finish running (synchronized)Stack Overflow