Target:
In this post we’ll discuss how to out of curiosity run easily complex
Javascript functionality in C# using WebBrowser control (however without using
WinForms).
Background:
We can achieve our target via building Web application where
one of the web pages will contain JavaScript code. JavaScript method can then be
invoked and its results can be returned to server (for instance with simple
JQuery).
However, we don’t want to build Web application just to execute
some single JavaScript function (but with important output).
So is it possible to run JavaScript in C# without heavy artillery?
So is it possible to run JavaScript in C# without heavy artillery?
After quick googling, we’ve found couples of tools, most prominent and free are Jint and Javascript.Net.
Both open sources are pretty easy to use in case we want to
run simple JavaScript code.
But what happens when JavaScript resides at some 3rd
party website and obfuscated?
JavaScript interpreter is not enough in such case, we need
browser capabilities in order to load 3rd party obfuscated
JavaScript module and run its methods.
With a little help from Google and combining suggestions and
tricks from different sources, we compiled a nice solution.
1.Creation of static HTML page
First of all, we created a static HTMLpage HTMLPage1.html
with all the relevant scripts definitions. In following example, we’ve created a
sample page with 2 references:
1. Reference to obfuscated online 3rd party
JavaScript Api which contain class ApiClass with asynchronous function
DoSomething().
2. Reference to custom JavaScript file that we created and
it is situated at our output directory
In the body of the page, we wrapped calls to both our and
external JavaScript API methods with simple functions that receives a list of
parameters (in the examples below only one parameter, but it can be freely
extended to more) and a callback (will be discussed later)
<html> <head> <script type="text/javascript" src="myJsClass.js"></script> <script type="text/javascript" src="http://someObfuscatedApi"></script> <title>Hi</title> </head> <body> <script type="text/javascript"> function CallJsMethod(jsParameter, callback) { someClass = new someObfuscatedAPI.ApiClass(); return someClass.DoSomething(jsParameter,function(result){ callback(result); }); } function CallMyJsMethod(jsParameter, callback) { someOtherClass = new myJsClass.MyApiClass(); var result = someOtherClass.DoSomethingElse(jsParameter); callback(result); } </script> </body> </html>
2.Running WebBrowser control
Next step is to create and to execute the WebBrowser control
in our module.
WebBrowser is a Windows.Forms control, as such it should be
executed as Single-Threaded Apartment (STA) process.
In order to start using JavaScript it should be fully loaded
in a browser (and we know that from a DocumentCompleted event of the browser).
The following code will do the trick:
public class JsExecuter { private string m_JsMethod; private object[] m_JsParameters; public void ExecuteJavaScript(string jsMethod, object[] jsParameters) { m_JsMethod = jsMethod; m_JsParameters = jsParameters; runBrowserThread(); } private void runBrowserThread() { var th = new Thread(() => { using (WebBrowser webBrowser = new WebBrowser() { InitBrowser(webBrowser); Application.Run(); } }); th.SetApartmentState(ApartmentState.STA); th.Start(); } //load our html page and so all the referenced scripts inside private void InitBrowser(WebBrowser webBrowser) { webBrowser.DocumentCompleted += browser_DocumentCompleted; string curDir = Directory.GetCurrentDirectory(); webBrowser.Url = new Uri(String.Format("file:///{0}/HTMLPage1.html",curDir)); } private void browser_DocumentCompleted (object sender, WebBrowserDocumentCompletedEventArgs e) { WebBrowser br = sender as WebBrowser; br.Document.InvokeScript(m_JsMethod,m_JsParameters); } }
3.Calling the module and using the callback
Now we know how to create a WebBrowser control and make the
call to JavaScript methods from it.The last thing that is left to do is to
explain how to use the callbacks.
public delegate void ResultArrivedHandler(string results); // in order to allow communication from JavaScript //[ComVisible(true)] should be defined [ComVisible(true)] public class CallBack { public ResultArrivedHandler ResultArrived { get; set; } //indicates default member for the object. It allows us to pass //CallBack instance directly to JavaScript, and so JavaScript will //invoke its default member [DispId(0)] public void Call(string result) { Application.ExitThread(); if (ResultArrived != null) { ResultArrived(result); } } }
In the code above we defined a class named CallBack. An instance
of this class will be passed as a callback to our JavaScript wrapper methods (see
Creation of static Html page section).
When a result arrives from JavaScript, the ResultArrived
event will be raised to notify our module’s clients.
4.Sample client code:
class Program { static void Main(string[] args) { CallBack cb = new CallBack(); cb.ResultArrived += new ResultArrivedHandler(x =>Console.WriteLine(x)); JsExecuter gs = new JsExecuter(); // last parameter in parameter list will be callback object gs.ExecuteJavaScript("CallJsMethod", new object[] { "some parameter", cb }); } }
Here we created a CallBack object and subscribed to its
ResultArrived event (just prints the results to Output).
Then, we just called to our module. Notice how the parameters
and especially CallBack instance were passed (the CallBack instance is the last
parameter !).
Epilogue:
That’s all! Simple and elegant solution for pretty tricky
problem.
But there is still one big con for this solution and it’s of
course the use of the WebBrowser control.
Yes, memory leak issues are still there and weren’t solved (online
discussion thread: http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/88c21427-e765-46e8-833d-6021ef79e0c8).
It’s not a big deal if your application doesn’t run a lot of
JavaScript methods.
However if it runs for hours and performs thousands calls to
a module above then depending on your machine it can hang or stuck.
Knowledge about the latest and vital technology would increase one's self esteem to the core at the time of lagging confidence. The content presented here is quite resembling the same. You have done a great job by sharing this in here.
ReplyDeleteBest JAVA Training institute in Chennai | Best JAVA Training in Chennai | Hadoop training in chennai
Great post you could have completed the following. I'm truly happy to learn to read this kind of. This can be a very informative subject matter that you're picked. keep writing guerrilla marketing strategies
ReplyDeleteThe blog gave me an idea to integrate java script with dot net. Thanks for sharing it
ReplyDeleteDot Net Training in Chennai
These are incredible as tester arranger and can hold back check whether the destruct couple of unencumbered message that is seized from the bed work. Java
ReplyDeleteLearning about energy and how it can be best utilized for betterment of mankind. Indeed most of the industries associated with the energy usage have started understanding about electrical power systems and engineering.
ReplyDeleteview our floodspro site
This is the awesome post and I have huge information from your creative blog. The admin presented the content is very interesting and also comprehensive. Thank you for your sharing, Keep updating...
ReplyDeleteOracle Training in Chennai
Oracle Training institute in chennai
Tableau Training in Chennai
Spark Training in Chennai
Unix Training in Chennai
Power BI Training in Chennai
Oracle DBA Training in Chennai
Oracle Training in Chennai
Oracle Training institute in chennai
ReplyDeleteAwesome blog. Thanks for sharing such a worthy information....
Python Training in Bangalore
Python Classes in Pune
Python Training in Hyderabad
This comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteslot siteleri
ReplyDeletekralbet
betpark
tipobet
betmatik
kibris bahis siteleri
poker siteleri
bonus veren siteler
mobil ödeme bahis
SZO2H
Thanks for sharing Blog . Keep sharing ! Java Course in Pune
ReplyDeleteVery nice blog , thanks for sharing Power bi Training in Pune
ReplyDeleteSuperb Post. Thanks for sharing.
ReplyDeleteJava Training in Pune
شركة مكافحة النمل الابيض بالاحساء ZxsSSaHmXm
ReplyDeleteGreat Post.
ReplyDeletealso, join Full-stack Java course in Pune