Embedding a WebBrowser control in a C# application is very easy to do. Simply drag and drop one in the Form editor. So what can you do with it besides writing your own web browser?
I wanted to load my own HTML page and call JavaScript functions within it and for the JavaScript to be able to call functions in C#. Specifically, I wanted to be able to interact with a public JavaScript API from Google (Google Maps) from the application.
Most of this can be accomplished using a pure JavaScript implementation in a web page, but the user interface is limited as is access to local computer resources, such as files. With a web server you can process uploaded files, but that requires server resources and a scalable infrastructure if you distribute your application. It is easier and cheaper to do file processing on the client, which is even more important in a freely distributed application to eliminate extra cost.
I searched around online and it was difficult to find details on how to call JavaScript from a containing C# application. It turns out to be really easy and worth sharing in case anyone else ever wants to do something similar.
Calling JavaScript from C# (See the next section for how to call C# from JavaScript).
So how can you call JavaScript functions in your WebBrowser control? Call the InvokeScript method on the HtmlDocument.
C#
namespace System.Windows.Forms { public sealed class HtmlDocument { public object InvokeScript(string scriptName); public object InvokeScript(string scriptName, object[] args); } }
For example, let’s assume that you have a System.Windows.Forms.WebBrowser object named webBrowser1 and you want to call a JavaScript function in the HTML page loaded in your WebBrowser called "showMe()"
JavaScript
function showMe() { ... }
C#
webBrowser1.Document.InvokeScript("showMe");
Adding parameters gets a bit more complicated, but not much. You can create an array of parameters as the API suggests and they will be passed in to the JavaScript function. However, there is an even simpler way to do it.
We will start by calling the following function
JavaScript
function showMe(x,y) { ... }
Let’s write a wrapper function in C# using the params keyword to let the compiler do the work for us. It will automatically convert any extra parameters into an array of objects, just like InvokeScript is expecting.
C#
private object MyInvokeScript(string name, params object[] args)
{
return webBrowser1.Document.InvokeScript(name, args);
}…
int x = 50;
int y = 100;
MyInvokeScript("showMe",x, y);
Note that the InvokeScript will return the value that the JavaScript function returns. According to the documentation, if it is a native type such as a number or string, it will be returned as a string, but it can also return an object.
JavaScript
function createPoint(x, y)
{
// Assume I have a Point object
var p = new Point(x,y);
return p;
}function setPoint (p)
{
// Do something useful with the Point p.
}
C#
object o = MyInvokeScript("createPoint", 50, 100);
It is possible to query information about the object using GetType and InvokeMember but I like that the object can be passed back into JavaScript
C#
MyInvokeScript("setPoint", o);
This is very powerful and, combined with the ability to call from JavaScript into C#, can allow you to embed many web applications that provide a JavaScript API into your C# application.
Calling C# from JavaScript
Simply put, you can expose a C# object to the WebBrowser that the JavaScript can call directly The WebBrowser class exposes a property called ObjectForScripting that can be set by your application and becomes the window.external object within JavaScript. The object must have the ComVisibleAttribute set true
C#
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class ScriptInterface
{
void callMe()
{
… // Do something interesting
}
}webBrowser1.ObjectForScripting = new ScriptInterface();
JavaScript
window.external.callMe();
What next?
With the ability to call JavaScript from C# and C# from JavaScript you can now embed and extend web applications into native applications with ease. A native application gives you more control over the environment and access to computer resources that you cannot access from a web page. You can merge, or "mashup", web applications with computer hardware or software in new and interesting ways.
Imagine accessing a GPS connected to your computer and view your current location in an embedded map powered by Google Maps. What if that included turn by turn directions to your destination? Why not go even further and convert the directions into speech? Doing all this on the client saves costs and pushes processing from expensive server hardware to client hardware and opens up interesting mashups to average users who do not have the resources to support their interesting idea for thousands of users.
Thank you very much!!! After taking the time to learn how to work around Silverlight I was heavily disappointed by the fact that it can not be used to access with local files. Atleast I found no information supporting otherwise. My fallback plan was to create a Winform application. This info is the final piece I needed to move ahead.
The code you are describing is the same I have found but at the moment I am working with AxWebBrowser instead of the WebBrowser control included in the .NET framework.
In this AxWebBrowser control I cannot find the equivalent of ObjectForScripting. Do you know how to get this to work?
Or better, do you have any knowledge on, how to get the WebBrowser control to handle opening of new browser windows and maintain session? 🙂
Great article, concise and to the point! Thanks to your text I managed to include a browser window doing Javascript commands to a web application in my windows application i 5 minutes.
This is great! I was looking to implement google maps in my application and needed exactly what you have here. One note on your code: In your class “ScriptInterface”, I had to make “CallMe” a public method.
Hello, I found this blog post while searching for help with JavaScript. I’ve recently switched browsers from Opera to Internet Explorer 7. Now I seem to have a problem with loading JavaScript. Everytime I go on a page that needs Javascript, my browser doesn’t load and I get a “runtime error javascript.JSException: Unknown name”. I cannot seem to find out how to fix the problem. Any aid is greatly appreciated! Thanks
Thank you. Your summary is concise and aimed exactly at what I was trying to do. With some minor changes to work with C++, your code got me going within a couple of hours. Nowhere else is this info summarized in one place. Particularly gratifying was seeing fields in my window update live with changes in the Google Earth view.
Thanks for this useful write-up. I’m surprised how simple it is to access the hosting application from a script in the browser control; I would hardly have imagined it possible.
Thanks buddy !!! Helped me a lot…
Thank you! You have given me exactly what I was looking for to advance a project I am working on. Very well written, easy to follow, perfect guide!
Article proved to be very helpful! Thank you for taking the time for writing it!
– Alex
I am also using this technique to call google analytics event tracking from inside a windows application. So i can peform analytics on win forms…
This blog has bolstered my decision to roll it out and see what happens..
great stuff!
Jscript
function trackEvent(category, action, opt_label, opt_value)
{
_gaq.push([‘_trackEvent’, category, action, opt_label, opt_value]);
}
C#
webBrowser1.Document.InvokeScript(“trackEvent”, args).ToString();
Very great article ! Thanks a lot.
Can I ask if this use will be the same to get back the javascript errors ?
To simplify the request, a major code will be release on a lot of sites and only javascript errors are able to be occur. So, thanks to the web browser, can I list the website and theirs javascript errors ?
Nice day to you.
Regards.
Steve.
Hi..Have you tried use webkit with webkitdotnet or xull runner mozilla with moznet??..I wish give a try them but the documentation is really poor..please if you’ve used some they would be nice see how do this in they…
I cant pass a list of string from C# to javascript:
i have in C#:
MyInvokeScript(“calcHistory”, coordenadas);
in javascript, i have:
function calcHistory(z)
but don’t work :s
can help me?
Calling C# from JavaScript
callMe function doesn’t work. Why doesn’t this function work?
JS say: …no property or function callMe
I found solution 🙂 You need to add keyword “public” before CallMe.
Thank you so much 😉
Pingback: Is it possible to drag a WPF element & handle drop in a WebBrowser with JavaScript?CopyQuery CopyQuery | Question & Answer Tool for your Technical Queries,CopyQuery, ejjuit, query, copyquery, copyquery.com, android doubt, ios question, sql query,
Pingback: Come integrare la comunicazione Wildix agli applicativi Web | Wildix Blog
I had been searching for this clearly-explained and straightforward exampkle for hours.
Thanks for the trouble you took to put this online.
Ian
Pingback: Is it feasible to pull handle fall a WPF component & in a WebBrowser with JavaScript? | CodersDiscuss.com
Could you use this to run all scripts on webpages, for example if i went on a random webpage that had javascript on it would it be able to run all of the scripts that the pages wan’t to run?
Hi,
Do you perhaps have a working demo with sourcecode.
I’m new to C# and would love to learn more
Hi,
I have question. Can I get access in c# to properties or methods of javascript object?
e.g.
Javascript:
function someAction () {
var key = “a”;
var value = 10;
var obj = {key: key, value: value};
return obj;
}
c#
object result = webBrowser1.Document.InvokeScript(“someAction”);
int resValue = result.value; //?
Pingback: Como comunicar um aplicativo local com uma pagina web aberta no browser? – World Magazine
Ten years later thank you very much! Great article very helpful…
Pingback: ??? ?????????? ?? ??????? ?????????????? ????????
Pingback: ??? ?????????? ?? ??????? ????
Pingback: WebBrowser control and JavaScript errors – w3toppers.com