How to inject Javascript in WebBrowser control?
Solution 1
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.
Solution 2
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.
Solution 3
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.
Solution 4
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);
Solution 5
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.
Related videos on Youtube
Comments
-
caseyamcl almost 2 years
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?
-
caseyamcl over 15 yearsASP.Net doesn't have much to do with scripting the WebBrowser control in a winforms app.
-
Grank over 15 yearsI probably would have under-read the same way and given the same incorrect answer
-
caseyamcl over 15 yearsNice... this together with the tips provided by korchev works perfectly. I wish I could set two accepted solutions on this one. :)
-
caseyamcl over 15 yearsNice tip... I'm sure that lib will come in handy at some point.
-
ZeroBugBounce over 15 yearsCool, I think the IHTMLScriptElement usage makes the code intent more obvious in any case. I do wonder why you got an exception, but c'est la vie with COM interop sometimes.
-
alimbada over 13 yearsWhy would anyone need dynamic for that? If you're trying to save some typing, we do have type inference since C# 3.0 so var would be acceptable. There's no need to start invoking the DLR.
-
IAmAN00B over 13 yearsWhat about adding a reference to a local js file? Please see stackoverflow.com/questions/4029602/…
-
justin.m.chase over 13 yearsThis is basically exactly the point of the dynamic keyword: COM interop. You don't actually have Type Inference here, you have documentation. Because an IHTMLElement2 is not assignable from IHtmlElement for example, and at runtime you just have a COM proxy object. You just have to know which interfaces to cast into what. The dynamic keyword helps you cut down on a lot of that cruft. You know the method exists why cast it into some interface? It doesn't exactly 'invoke the DLR' it just generates code that knows how to invoke method on COM objects (in this case).
-
Johnydep almost 13 yearsPlease help me with this. How did you do this. I want to inject JS into my page in real time through my C++ app. How should i go about it.
-
Kyeotic over 12 yearsAs this is a community resource, his answer is still useful to others (like myself). +1 for mshtml equivalent, saved me a question.
-
Kyeotic over 12 yearsFor anyone that finds this, remove 'class' from the last line, should read
((HTMLHeadElement)head).appendChild((IHTMLDOMNode)scriptObject);
you will get errors otherwise. -
Micah Smith over 12 yearsI appreciated this solution because it doesn't rely on the (albeit useful!) IHTMLSCriptElement assembly.
-
justin.m.chase over 11 yearsIs there anyway this answer can get promoted by admins? The ones above this are all wrong in reality. This one was a late comer but really is the most correct answer.
-
BlueRaja - Danny Pflughoeft over 10 years@jsight This should be the accepted answer. It is the same as the current answer, but simpler and without the
IHTMLSCriptElement
dependency. -
Chris Hobbs over 8 yearsI know this was answered 3 days short of a year ago, but would you be able to use this to put a file into an
input type="file"
section? -
Khizar Iqbal over 6 years@justin.m.chase you saved my life.
-
gumuruh almost 4 yearsis this applicable to inject jquery file also?