Skip to content

Instantly share code, notes, and snippets.

@lawliet89
Last active October 12, 2022 13:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lawliet89/fcb674be06ec9a50b825 to your computer and use it in GitHub Desktop.
Save lawliet89/fcb674be06ec9a50b825 to your computer and use it in GitHub Desktop.
Calling Javascript Object Method in a System.Windows.Forms.WebBrowser Contorl
using System;
using System.Linq;
using System.Web.Script.Serialization;
using System.Windows.Forms;
namespace AsynchronousWebPage
{
/// <summary>
/// Extension convenience methods to invoke arbitrary Javascript method on a web page
/// hosted by a WebBrowser control.
/// This extensions makes use of the <see cref="System.Web.Script.Serialization.JavaScriptSerializer" />
/// object to serialise objects to JSON. You might need to add a reference to the
/// System.Web.Extensions assembly.
/// </summary>
public static class WebBrowserExtensions
{
/// <summary>
/// Invoke an arbitrary Javascript function on a hosted web page
/// Beware of the pitfall of calling this before a document has loaded: https://msdn.microsoft.com/en-us/library/cc491132.aspx
/// </summary>
/// <param name="browser">The WebBrowser control</param>
/// <param name="function">The name of the Javascript function to execute. For example, "object.foobar"</param>
/// <param name="argObjects">An array containing arguments to the function. The arguments will be serialised to JSON.</param>
/// <returns>The result from the Javascript function, if any.</returns>
public static Object InvokeScript(this WebBrowser browser, string function, params object[] argObjects)
{
var javaScriptSerializer = new JavaScriptSerializer();
var args = String.Join(",",
argObjects.Select(o => javaScriptSerializer.Serialize(o)));
const string script = "{0}({1});";
return browser.InvokeScript(String.Format(script, function, args));
}
/// <summary>
/// Invoke arbitrary Javascript code on a hosted web page
/// Beware of the pitfall of calling this before a document has loaded: https://msdn.microsoft.com/en-us/library/cc491132.aspx
/// </summary>
/// <param name="browser">The WebBrowser control</param>
/// <param name="script">Arbitrary Javascript code</param>
/// <returns>The result from the Javascript function, if any.</returns>
public static Object InvokeScript(this WebBrowser browser, string script)
{
if (browser.Document == null)
{
throw new InvalidOperationException("There is no document loaded in the WebBrowser control");
}
// Ugly workaround: http://stackoverflow.com/questions/7322420/
var selfExecutingScript = @"(function () { 'use strict'; function execute() { " + script +
@" } return execute(); }());";
// We can only call the InvokeScript method in the thread that owns the WebBrowser control.
// Thus, we have to execute this via delegate using the Invoke method on the browser control.
var action =
new Func<object>(() => browser.Document.InvokeScript("eval", new object[] {selfExecutingScript}));
return browser.Invoke(action);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment