I'm doing some web automation via C# and a WebBrowser. There's a link which I need to 'click', but since it fires a Javascript function, apparently the code needs to be executed rather than just having the element clicked (i.e. element.InvokeMember("click")). Here's the href for the element, which opens an Ajax form:
javascript:__doPostBack("ctl00$cphMain$lnkNameserverUpdate", "")
I've tried:
webBrowser1.Document.InvokeScript("javascript:__doPostBack", new object[] { "ctl00$cphMain$lnkNameserverUpdate", "" });
and:
webBrowser1.Document.InvokeScript("__doPostBack", new object[] { "ctl00$cphMain$lnkNameserverUpdate", "" });
and a few other things. The code gets hit, but the script doesn't get fired. Any ideas would be most appreciated.
Gregg
BTW Here's the full element in case it's useful:
NS51.DOMAINCONTROL.COM<br/>NS52.DOMAINCONTROL.COM<br/>
Have a look at this link:
http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.objectforscripting.aspx
I've actually used this in the past, and it works perfectly.
HtmlDocument doc = browser.Document;
HtmlElement head = doc.GetElementsByTagName("head")[0];
HtmlElement s = doc.CreateElement("script");
s.SetAttribute("text","function sayhello() { alert('hello'); }");
head.AppendChild(s);
browser.Document.InvokeScript("sayHello");
Related
I have an HTML document with an iFrame, which i am loading in a webbrowser window. My objective is once that iFrame document is loaded, capture the document contents and search for a particular line.
I am not been able to do it so far, any suggestions ?
HTML CODE
<html>
<body>
<iframe id="monitor" src="http://monitor.baseline.com"></iframe>
</body>
</html>
You can add a JavaScript function to the OnLoad event of the iFrame:
document.getElementById('monitor').onload = function() { }
And then follow these solutions to parse your document. But be aware about cross-site-scripting restrictions. If the src of your iFrame is a totally different domain, it probably won't work.
i got it by doing the below
var javascript = #"
var Frame = document.getElementById('monitor');
window.external.iFrameCheck(Frame.contentWindow.document);
";
var doc = (IHTMLDocument2)webBrowser1.Document;
//Once we have the document, execute our JavaScript in it
doc.parentWindow.execScript(javascript);
this would then call the below c# code
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
[ComVisible(true)]
public class ComVisibleObjectForScripting
{
public void iFrameCheck(HTMLDocument FrameDoc)
{
//Do what you want here with your FrameDoc
// the innerHTML will give you the content of the iframe
}
}
First I tried to run from a WebBrowser Control
WebBrowser webBrowser1 = new WebBrowser();
webBrowser1.Visible = false;
webBrowser1.Navigate("about:blank");
webBrowser1.Document.Write("<html><head></head><body></body></html>");
HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
dynamic scriptEl = webBrowser1.Document.CreateElement("script");
scriptEl.DomElement.text = "function test(fn) { try{ window[fn](); } catch(ex) { return 'abc '.trim(); } }"
+ "function sayHello() { alert('ha'); throw 'error with spaces '; }";
head.AppendChild(scriptEl);
var result = webBrowser1.Document.InvokeScript("test", new object[] { "sayHello" });
It works almost perfectly. It knows what a window, alert is... The only problem is that it apparently runs on ECMA3, so when I tested "abc ".trim() it couldn't execute.
My second attempt was Javascript .NET.
using (JavascriptContext context = new JavascriptContext())
{
// Setting external parameters for the context
//context.SetParameter("console", new SystemConsole());
context.SetParameter("message", "Hello World ! ");
// Script
string script = #"
alert(message.trim());
";
// Running the script
context.Run(script);
}
Unfortunately it doesn't know what alert, window, document, console... is. Unless I tell it setting context parameters.
What else is there? May I should try some headless browsers and invoke using Process?
If you want to run JavaScript server side, I would recommend using PhantomJS. It allows you to run a full WebKit browser from the command line using JavaScript and command line arguments.
JavaScript is definitely not just for client-side scripting any more. As Cameron said PhantomJS is excellent if you need the DOM. If you don't, NodeJS is the clear choice with a wealth of libraries.
I am using WPF WebBrowser control and I want to acces some of the JavaScript functions but there is the problem.
I can use InvokeScript and execute browser.InvokeScript("alert", "Hello");q but how to get element by ID or by TAG and how to assign that element to javascript var?
Example:
Javascript:
var elements = document.getElementsByTagName("embed");
elements[0].doSomething();
C#:
How?
I tryed everything but nothing worked. Can anyone help me :(
Quite a late answer, but if anyone else needs it:
The direct C#: http://msdn.microsoft.com/en-us/library/system.windows.forms.htmldocument.getelementsbytagname.aspx
HtmlElementCollection elems = webBrowser1.Document.GetElementsByTagName("embed");
foreach (HtmlElement elem in elems)
{
elem.InvokeMember("doSomething");
}
The alternative: http://msdn.microsoft.com/en-us/library/a0746166
Basically you should create a function in JS:
var myCustomFunc = function(tagName) {
var elements = document.getElementsByTagName(tagName); elements[0].doSomething();
}
And then call it from C# with
webBrowser1.Document.InvokeScript("myCustomFunc ", new String[] { "embed" });
The variable "tagName" gets replaced with "embed"
I've tried this:
string newScript = textBox1.Text;
HtmlElement head = browserCtrl.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = browserCtrl.Document.CreateElement("script");
lblStatus.Text = scriptEl.GetType().ToString();
scriptEl.SetAttribute("type", "text/javascript");
head.AppendChild(scriptEl);
scriptEl.InnerHtml = "function sayHello() { alert('hello') }";
scriptEl.InnerHtml and scriptEl.InnerText both give errors:
System.NotSupportedException: Property is not supported on this type of HtmlElement.
at System.Windows.Forms.HtmlElement.set_InnerHtml(String value)
at SForceApp.Form1.button1_Click(Object sender, EventArgs e) in d:\jsight\installs\SForceApp\SForceApp\Form1.cs:line 31
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Is there an easy way to inject a script into the dom?
For some reason Richard's solution didn't work on my end (insertAdjacentText failed with an exception). This however seems to work:
HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = webBrowser1.Document.CreateElement("script");
IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement;
element.text = "function sayHello() { alert('hello') }";
head.AppendChild(scriptEl);
webBrowser1.Document.InvokeScript("sayHello");
This answer explains how to get the IHTMLScriptElement interface into your project.
HtmlDocument doc = browser.Document;
HtmlElement head = doc.GetElementsByTagName("head")[0];
HtmlElement s = doc.CreateElement("script");
s.SetAttribute("text","function sayHello() { alert('hello'); }");
head.AppendChild(s);
browser.Document.InvokeScript("sayHello");
(tested in .NET 4 / Windows Forms App)
Edit: Fixed case issue in function set.
Here is the easiest way that I found after working on this:
string javascript = "alert('Hello');";
// or any combination of your JavaScript commands
// (including function calls, variables... etc)
// WebBrowser webBrowser1 is what you are using for your web browser
webBrowser1.Document.InvokeScript("eval", new object[] { javascript });
What global JavaScript function eval(str) does is parses and executes whatever is written in str.
Check w3schools ref here.
Also, in .NET 4 this is even easier if you use the dynamic keyword:
dynamic document = this.browser.Document;
dynamic head = document.GetElementsByTagName("head")[0];
dynamic scriptEl = document.CreateElement("script");
scriptEl.text = ...;
head.AppendChild(scriptEl);
If all you really want is to run javascript, this would be easiest (VB .Net):
MyWebBrowser.Navigate("javascript:function foo(){alert('hello');}foo();")
I guess that this wouldn't "inject" it but it'll run your function, if that's what you're after. (Just in case you've over-complicated the problem.) And if you can figure out how to inject in javascript, put that into the body of the function "foo" and let the javascript do the injection for you.
The managed wrapper for the HTML document doesn't completely implement the functionality you need, so you need to dip into the MSHTML API to accomplish what you want:
1) Add a reference to MSHTML, which will probalby be called "Microsoft HTML Object Library" under COM references.
2) Add 'using mshtml;' to your namespaces.
3) Get a reference to your script element's IHTMLElement:
IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;
4) Call the insertAdjacentText method, with the first parameter value of "afterBegin". All the possible values are listed here:
iScriptEl.insertAdjacentText("afterBegin", "function sayHello() { alert('hello') }");
5) Now you'll be able to see the code in the scriptEl.InnerText property.
Hth,
Richard
I believe the most simple method to inject Javascript in a WebBrowser Control HTML Document from c# is to invoke the "execScript" method with the code to be injected as argument.
In this example the javascript code is injected and executed at global scope:
var jsCode="alert('hello world from injected code');";
WebBrowser.Document.InvokeScript("execScript", new Object[] { jsCode, "JavaScript" });
If you want to delay execution, inject functions and call them after:
var jsCode="function greet(msg){alert(msg);};";
WebBrowser.Document.InvokeScript("execScript", new Object[] { jsCode, "JavaScript" });
...............
WebBrowser.Document.InvokeScript("greet",new object[] {"hello world"});
This is valid for Windows Forms and WPF WebBrowser controls.
This solution is not cross browser because "execScript" is defined only in IE and Chrome. But the question is about Microsoft WebBrowser controls and IE is the only one supported.
For a valid cross browser method to inject javascript code, create a Function object with the new Keyword. This example creates an anonymous function with injected code and executes it (javascript implements closures and the function has access to global space without local variable pollution).
var jsCode="alert('hello world');";
(new Function(code))();
Of course, you can delay execution:
var jsCode="alert('hello world');";
var inserted=new Function(code);
.................
inserted();
Hope it helps
As a follow-up to the accepted answer, this is a minimal definition of the IHTMLScriptElement interface which does not require to include additional type libraries:
[ComImport, ComVisible(true), Guid(#"3050f28b-98b5-11cf-bb82-00aa00bdce0b")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
[TypeLibType(TypeLibTypeFlags.FDispatchable)]
public interface IHTMLScriptElement
{
[DispId(1006)]
string text { set; [return: MarshalAs(UnmanagedType.BStr)] get; }
}
So a full code inside a WebBrowser control derived class would look like:
protected override void OnDocumentCompleted(
WebBrowserDocumentCompletedEventArgs e)
{
base.OnDocumentCompleted(e);
// Disable text selection.
var doc = Document;
if (doc != null)
{
var heads = doc.GetElementsByTagName(#"head");
if (heads.Count > 0)
{
var scriptEl = doc.CreateElement(#"script");
if (scriptEl != null)
{
var element = (IHTMLScriptElement)scriptEl.DomElement;
element.text =
#"function disableSelection()
{
document.body.onselectstart=function(){ return false; };
document.body.ondragstart=function() { return false; };
}";
heads[0].AppendChild(scriptEl);
doc.InvokeScript(#"disableSelection");
}
}
}
}
this is a solution using mshtml
IHTMLDocument2 doc = new HTMLDocumentClass();
doc.write(new object[] { File.ReadAllText(filePath) });
doc.close();
IHTMLElement head = (IHTMLElement)((IHTMLElementCollection)doc.all.tags("head")).item(null, 0);
IHTMLScriptElement scriptObject = (IHTMLScriptElement)doc.createElement("script");
scriptObject.type = #"text/javascript";
scriptObject.text = #"function btn1_OnClick(str){
alert('you clicked' + str);
}";
((HTMLHeadElementClass)head).appendChild((IHTMLDOMNode)scriptObject);
I used this :D
HtmlElement script = this.WebNavegador.Document.CreateElement("SCRIPT");
script.SetAttribute("TEXT", "function GetNameFromBrowser() {" +
"return 'My name is David';" +
"}");
this.WebNavegador.Document.Body.AppendChild(script);
Then you can execute and get the result with:
string myNameIs = (string)this.WebNavegador.Document.InvokeScript("GetNameFromBrowser");
I hope to be helpful
Here is a VB.Net example if you are trying to retrieve the value of a variable from within a page loaded in a WebBrowser control.
Step 1) Add a COM reference in your project to Microsoft HTML Object Library
Step 2) Next, add this VB.Net code to your Form1 to import the mshtml library:
Imports mshtml
Step 3) Add this VB.Net code above your "Public Class Form1" line:
<System.Runtime.InteropServices.ComVisibleAttribute(True)>
Step 4) Add a WebBrowser control to your project
Step 5) Add this VB.Net code to your Form1_Load function:
WebBrowser1.ObjectForScripting = Me
Step 6) Add this VB.Net sub which will inject a function "CallbackGetVar" into the web page's Javascript:
Public Sub InjectCallbackGetVar(ByRef wb As WebBrowser)
Dim head As HtmlElement
Dim script As HtmlElement
Dim domElement As IHTMLScriptElement
head = wb.Document.GetElementsByTagName("head")(0)
script = wb.Document.CreateElement("script")
domElement = script.DomElement
domElement.type = "text/javascript"
domElement.text = "function CallbackGetVar(myVar) { window.external.Callback_GetVar(eval(myVar)); }"
head.AppendChild(script)
End Sub
Step 7) Add the following VB.Net sub which the Javascript will then look for when invoked:
Public Sub Callback_GetVar(ByVal vVar As String)
Debug.Print(vVar)
End Sub
Step 8) Finally, to invoke the Javascript callback, add this VB.Net code when a button is pressed, or wherever you like:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
WebBrowser1.Document.InvokeScript("CallbackGetVar", New Object() {"NameOfVarToRetrieve"})
End Sub
Step 9) If it surprises you that this works, you may want to read up on the Javascript "eval" function, used in Step 6, which is what makes this possible. It will take a string and determine whether a variable exists with that name and, if so, returns the value of that variable.
You can always use a "DocumentStream" or "DocumentText" property.
For working with HTML documents I recommend a HTML Agility Pack.
i use this:
webBrowser.Document.InvokeScript("execScript", new object[] { "alert(123)", "JavaScript" })
What you want to do is use Page.RegisterStartupScript(key, script)
:
See here for more details: http://msdn.microsoft.com/en-us/library/aa478975.aspx
What you basically do is build your javascript string, pass it to that method and give it a unique id( in case you try to register it twice on a page.)
EDIT: This is what you call trigger happy. Feel free to down it. :)
If you need to inject a whole file then you can use this:
With Browser.Document
Dim Head As HtmlElement = .GetElementsByTagName("head")(0)
Dim Script As HtmlElement = .CreateElement("script")
Dim Streamer As New StreamReader(<Here goes path to file as String>)
Using Streamer
Script.SetAttribute("text", Streamer.ReadToEnd())
End Using
Head.AppendChild(Script)
.InvokeScript(<Here goes a method name as String and without parentheses>)
End With
Remember to import System.IO in order to use the StreamReader. I hope this helps.
bibki.js
webBrowser1.DocumentText =
"<html><head><script>" +
"function test(message) { alert(message); }" +
"</script></head><body><button " +
"onclick=\"window.external.Test('called from script code')\">" +
"call client code from script code</button>" +
"</body></html>";
I've tried this:
string newScript = textBox1.Text;
HtmlElement head = browserCtrl.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = browserCtrl.Document.CreateElement("script");
lblStatus.Text = scriptEl.GetType().ToString();
scriptEl.SetAttribute("type", "text/javascript");
head.AppendChild(scriptEl);
scriptEl.InnerHtml = "function sayHello() { alert('hello') }";
scriptEl.InnerHtml and scriptEl.InnerText both give errors:
System.NotSupportedException: Property is not supported on this type of HtmlElement.
at System.Windows.Forms.HtmlElement.set_InnerHtml(String value)
at SForceApp.Form1.button1_Click(Object sender, EventArgs e) in d:\jsight\installs\SForceApp\SForceApp\Form1.cs:line 31
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Is there an easy way to inject a script into the dom?
For some reason Richard's solution didn't work on my end (insertAdjacentText failed with an exception). This however seems to work:
HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = webBrowser1.Document.CreateElement("script");
IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement;
element.text = "function sayHello() { alert('hello') }";
head.AppendChild(scriptEl);
webBrowser1.Document.InvokeScript("sayHello");
This answer explains how to get the IHTMLScriptElement interface into your project.
HtmlDocument doc = browser.Document;
HtmlElement head = doc.GetElementsByTagName("head")[0];
HtmlElement s = doc.CreateElement("script");
s.SetAttribute("text","function sayHello() { alert('hello'); }");
head.AppendChild(s);
browser.Document.InvokeScript("sayHello");
(tested in .NET 4 / Windows Forms App)
Edit: Fixed case issue in function set.
Here is the easiest way that I found after working on this:
string javascript = "alert('Hello');";
// or any combination of your JavaScript commands
// (including function calls, variables... etc)
// WebBrowser webBrowser1 is what you are using for your web browser
webBrowser1.Document.InvokeScript("eval", new object[] { javascript });
What global JavaScript function eval(str) does is parses and executes whatever is written in str.
Check w3schools ref here.
Also, in .NET 4 this is even easier if you use the dynamic keyword:
dynamic document = this.browser.Document;
dynamic head = document.GetElementsByTagName("head")[0];
dynamic scriptEl = document.CreateElement("script");
scriptEl.text = ...;
head.AppendChild(scriptEl);
If all you really want is to run javascript, this would be easiest (VB .Net):
MyWebBrowser.Navigate("javascript:function foo(){alert('hello');}foo();")
I guess that this wouldn't "inject" it but it'll run your function, if that's what you're after. (Just in case you've over-complicated the problem.) And if you can figure out how to inject in javascript, put that into the body of the function "foo" and let the javascript do the injection for you.
The managed wrapper for the HTML document doesn't completely implement the functionality you need, so you need to dip into the MSHTML API to accomplish what you want:
1) Add a reference to MSHTML, which will probalby be called "Microsoft HTML Object Library" under COM references.
2) Add 'using mshtml;' to your namespaces.
3) Get a reference to your script element's IHTMLElement:
IHTMLElement iScriptEl = (IHTMLElement)scriptEl.DomElement;
4) Call the insertAdjacentText method, with the first parameter value of "afterBegin". All the possible values are listed here:
iScriptEl.insertAdjacentText("afterBegin", "function sayHello() { alert('hello') }");
5) Now you'll be able to see the code in the scriptEl.InnerText property.
Hth,
Richard
I believe the most simple method to inject Javascript in a WebBrowser Control HTML Document from c# is to invoke the "execScript" method with the code to be injected as argument.
In this example the javascript code is injected and executed at global scope:
var jsCode="alert('hello world from injected code');";
WebBrowser.Document.InvokeScript("execScript", new Object[] { jsCode, "JavaScript" });
If you want to delay execution, inject functions and call them after:
var jsCode="function greet(msg){alert(msg);};";
WebBrowser.Document.InvokeScript("execScript", new Object[] { jsCode, "JavaScript" });
...............
WebBrowser.Document.InvokeScript("greet",new object[] {"hello world"});
This is valid for Windows Forms and WPF WebBrowser controls.
This solution is not cross browser because "execScript" is defined only in IE and Chrome. But the question is about Microsoft WebBrowser controls and IE is the only one supported.
For a valid cross browser method to inject javascript code, create a Function object with the new Keyword. This example creates an anonymous function with injected code and executes it (javascript implements closures and the function has access to global space without local variable pollution).
var jsCode="alert('hello world');";
(new Function(code))();
Of course, you can delay execution:
var jsCode="alert('hello world');";
var inserted=new Function(code);
.................
inserted();
Hope it helps
As a follow-up to the accepted answer, this is a minimal definition of the IHTMLScriptElement interface which does not require to include additional type libraries:
[ComImport, ComVisible(true), Guid(#"3050f28b-98b5-11cf-bb82-00aa00bdce0b")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
[TypeLibType(TypeLibTypeFlags.FDispatchable)]
public interface IHTMLScriptElement
{
[DispId(1006)]
string text { set; [return: MarshalAs(UnmanagedType.BStr)] get; }
}
So a full code inside a WebBrowser control derived class would look like:
protected override void OnDocumentCompleted(
WebBrowserDocumentCompletedEventArgs e)
{
base.OnDocumentCompleted(e);
// Disable text selection.
var doc = Document;
if (doc != null)
{
var heads = doc.GetElementsByTagName(#"head");
if (heads.Count > 0)
{
var scriptEl = doc.CreateElement(#"script");
if (scriptEl != null)
{
var element = (IHTMLScriptElement)scriptEl.DomElement;
element.text =
#"function disableSelection()
{
document.body.onselectstart=function(){ return false; };
document.body.ondragstart=function() { return false; };
}";
heads[0].AppendChild(scriptEl);
doc.InvokeScript(#"disableSelection");
}
}
}
}
this is a solution using mshtml
IHTMLDocument2 doc = new HTMLDocumentClass();
doc.write(new object[] { File.ReadAllText(filePath) });
doc.close();
IHTMLElement head = (IHTMLElement)((IHTMLElementCollection)doc.all.tags("head")).item(null, 0);
IHTMLScriptElement scriptObject = (IHTMLScriptElement)doc.createElement("script");
scriptObject.type = #"text/javascript";
scriptObject.text = #"function btn1_OnClick(str){
alert('you clicked' + str);
}";
((HTMLHeadElementClass)head).appendChild((IHTMLDOMNode)scriptObject);
I used this :D
HtmlElement script = this.WebNavegador.Document.CreateElement("SCRIPT");
script.SetAttribute("TEXT", "function GetNameFromBrowser() {" +
"return 'My name is David';" +
"}");
this.WebNavegador.Document.Body.AppendChild(script);
Then you can execute and get the result with:
string myNameIs = (string)this.WebNavegador.Document.InvokeScript("GetNameFromBrowser");
I hope to be helpful
Here is a VB.Net example if you are trying to retrieve the value of a variable from within a page loaded in a WebBrowser control.
Step 1) Add a COM reference in your project to Microsoft HTML Object Library
Step 2) Next, add this VB.Net code to your Form1 to import the mshtml library:
Imports mshtml
Step 3) Add this VB.Net code above your "Public Class Form1" line:
<System.Runtime.InteropServices.ComVisibleAttribute(True)>
Step 4) Add a WebBrowser control to your project
Step 5) Add this VB.Net code to your Form1_Load function:
WebBrowser1.ObjectForScripting = Me
Step 6) Add this VB.Net sub which will inject a function "CallbackGetVar" into the web page's Javascript:
Public Sub InjectCallbackGetVar(ByRef wb As WebBrowser)
Dim head As HtmlElement
Dim script As HtmlElement
Dim domElement As IHTMLScriptElement
head = wb.Document.GetElementsByTagName("head")(0)
script = wb.Document.CreateElement("script")
domElement = script.DomElement
domElement.type = "text/javascript"
domElement.text = "function CallbackGetVar(myVar) { window.external.Callback_GetVar(eval(myVar)); }"
head.AppendChild(script)
End Sub
Step 7) Add the following VB.Net sub which the Javascript will then look for when invoked:
Public Sub Callback_GetVar(ByVal vVar As String)
Debug.Print(vVar)
End Sub
Step 8) Finally, to invoke the Javascript callback, add this VB.Net code when a button is pressed, or wherever you like:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
WebBrowser1.Document.InvokeScript("CallbackGetVar", New Object() {"NameOfVarToRetrieve"})
End Sub
Step 9) If it surprises you that this works, you may want to read up on the Javascript "eval" function, used in Step 6, which is what makes this possible. It will take a string and determine whether a variable exists with that name and, if so, returns the value of that variable.
You can always use a "DocumentStream" or "DocumentText" property.
For working with HTML documents I recommend a HTML Agility Pack.
i use this:
webBrowser.Document.InvokeScript("execScript", new object[] { "alert(123)", "JavaScript" })
What you want to do is use Page.RegisterStartupScript(key, script)
:
See here for more details: http://msdn.microsoft.com/en-us/library/aa478975.aspx
What you basically do is build your javascript string, pass it to that method and give it a unique id( in case you try to register it twice on a page.)
EDIT: This is what you call trigger happy. Feel free to down it. :)
If you need to inject a whole file then you can use this:
With Browser.Document
Dim Head As HtmlElement = .GetElementsByTagName("head")(0)
Dim Script As HtmlElement = .CreateElement("script")
Dim Streamer As New StreamReader(<Here goes path to file as String>)
Using Streamer
Script.SetAttribute("text", Streamer.ReadToEnd())
End Using
Head.AppendChild(Script)
.InvokeScript(<Here goes a method name as String and without parentheses>)
End With
Remember to import System.IO in order to use the StreamReader. I hope this helps.
bibki.js
webBrowser1.DocumentText =
"<html><head><script>" +
"function test(message) { alert(message); }" +
"</script></head><body><button " +
"onclick=\"window.external.Test('called from script code')\">" +
"call client code from script code</button>" +
"</body></html>";