I am trying to read the value of a Javascript variable which is loaded and called from a WebBrowser control on my form.
Example:
index.html refers to a javas
I do no think that you are going to be able to just get the value of your variable from your JS because your C# is going to run before your js var even exist. I have had this same issue myself with getting values of my js variables and I have not been able to do it directly. What you can do is use an HtmlTextWriter method to get the values. This will allow you to use a C# rendered js call that will give you access to your variable values.
For Example:
protected override void RenderContents(HtmlTextWriter writer)
{
EnsureChildControls();
base.RenderContents(writer);
writer.BeginRender();
writer.RenderBeginTag(HtmlTextWriterTag.Script);
writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
writer.Write("myJavaScriptVar = (\" + myC#Var + \")");
writer.RenderEndTag();
Not 100% that it will work, but I know that you can access your js variables this way. I have done this with other projects. Hope this helps.
To access global scope JavaScript variables, I used a custom method included here called GetGlobalVariable()
. (It uses Document.InvokeScript
from Juan's answer. +1)
Let's say your JavaScript variables created in the global scope like this:
var foo = "bar";
var person = {};
var person.name = "Bob";
Then you can access these values using the C# GetGlobalVariable()
method like so. (You may need to set up a timer to continually check if the variables are populated.)
var foo = GetGlobalVariable(webBrowser, "foo");
var name = GetGlobalVariable(webBrowser, "person.name");
Here is the GetGlobalVariable()
method. Notice it checks each part of variable reference to avoid an exception.
private object GetGlobalVariable(WebBrowser browser, string variable)
{
string[] variablePath = variable.Split('.');
int i = 0;
object result = null;
string variableName = "window";
while (i < variablePath.Length)
{
variableName = variableName + "." + variablePath[i];
result = browser.Document.InvokeScript("eval", new object[] { variableName });
if (result == null)
{
return result;
}
i++;
}
return result;
}
You can use IHTMLDocument::Script to retrieve the automation interface of the script engine. If you use the Windows Forms webbrowser control in C#, this means casting the HtmlDocument.DomDocument property to mshtml.IHTMLDocument. For WPF you cast the document directly.
Global variables are added to the script engine as properties and global functions as methods. Until IE9, you can use the IDispatch interface to access those functions/variables if you know their names. HtmlDocument.InvokeScript and WPF's WebBrowser.InvokeScript wraps this up in a nice way, but only for System.Reflection.BindingFlags.InvokeMethod. For accessing variables you need to pass DISPATCH_PROPERTYGET when you call Invoke, that is, use BindingFlags.GetProperty in managed code.
Manual late binding is not fun, In case you want to know how laborious late binding is, check Binding for Office automation servers with Visual C# .NET.
There is a problem in IE9 that the variables/functions are not accessible via IDispatch, but you can still access variables/functions via IDispatchEx in a similar way.
I think this is really a scoping question. If you include a file called test.js and in that file you have this line:
var myVariable;
Then that variable is created with global scope and is accessible from anywhere in your page and also in any other JavaScript files that you include. If you declare a variable like that, outside of a function, it will be created with global scope.
One thought. If you're not able to access your variable in your main page then make sure that your script that declares it and assigns a value is included before the JavaScript on your page tries to use it. You could have an order of execution problem.
You could do:
Document.InvokeScript("eval", new object[] { "my_var_name" });
Take a look at the HtmlWindow Class. You can get an instance of it from WebBrowser.Document.Window
. If your js variables have global scope, they will belong to the Window object, and should be accessible from WebBrowser.Document.Window.DomWindow
in C#.