在WebBrowser中调用脚本,并等待它完成运行(同步)

我正在使用webBrowser.Document.InvokeScript("Function")来运行javascript,它位于使用Winforms WebBrowser打开的本地文件中。

问题是,我需要javascript在继续之前完成执行。 我该如何等待/倾听?

这是我的C#代码:

  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代码:

 function Script_A() { Script_B(); } 

如何在Script_B完成之前确保没有执行Method_A?

使用async / await可以等到执行脚本而不阻塞UI。

 public async void AMethod() { string script = @""; TaskCompletionSource tcs = new TaskCompletionSource(); 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 _tcs = null; public CallbackObject(TaskCompletionSource tcs) { _tcs = tcs; } public void Completed() { _tcs.TrySetResult(true); } } public static class BrowserExtensions { public static Task SetDocumentTextAsync(this WebBrowser wb, string html) { TaskCompletionSource tcs = new TaskCompletionSource(); WebBrowserDocumentCompletedEventHandler completedEvent = null; completedEvent = (sender, e) => { wb.DocumentCompleted -= completedEvent; tcs.SetResult(null); }; wb.DocumentCompleted += completedEvent; wb.ScriptErrorsSuppressed = true; wb.DocumentText = html; return tcs.Task; } } 

您需要实现一个回调方法(不要忘记ComVisible-Attribute ),您将使用脚本调用该方法

 window.mymethod(); 

这样,您实际上需要“拆分”您的方法。

这是SO的一篇不错的post。


这是一个教程:

从WebBrowser中托管的JavaScript调用C#方法

作者:AspDotNetDev,2011年5月6日

此示例演示如何从JavaScript调用C#。 它还显示参数可以传递给C#方法。

首先,创建一个Windows窗体应用程序。 然后,将WebBrowser控件添加到窗体。 然后修改表单的代码,使其如下所示:

  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 = @"  Test    
"; } } }

请注意,您的应用程序可能是WindowsFormsApplication6以外的命名空间的一部分,但如果您明确遵循上述说明,则其余代码应该可用。 我创建了这个提示/技巧,因为有人问我一个问题,他们不理解我发送给他们的这个样本。 这个提示/技巧通过修复我发现的两个错误,添加未提及的using语句,以及大量注释代码,使样本更容易理解。 希望你们其他人也会发现这个用途。 执照