How to inject Javascript in WebBrowser control?

169,687

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.

Share:
169,687

Related videos on Youtube

caseyamcl
Author by

caseyamcl

I'm a Java and .Net programmer.

Updated on July 05, 2022

Comments

  • caseyamcl
    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
    caseyamcl over 15 years
    ASP.Net doesn't have much to do with scripting the WebBrowser control in a winforms app.
  • Grank
    Grank over 15 years
    I probably would have under-read the same way and given the same incorrect answer
  • caseyamcl
    caseyamcl over 15 years
    Nice... this together with the tips provided by korchev works perfectly. I wish I could set two accepted solutions on this one. :)
  • caseyamcl
    caseyamcl over 15 years
    Nice tip... I'm sure that lib will come in handy at some point.
  • ZeroBugBounce
    ZeroBugBounce over 15 years
    Cool, 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
    alimbada over 13 years
    Why 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
    IAmAN00B over 13 years
    What about adding a reference to a local js file? Please see stackoverflow.com/questions/4029602/…
  • justin.m.chase
    justin.m.chase over 13 years
    This 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
    Johnydep almost 13 years
    Please 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
    Kyeotic over 12 years
    As this is a community resource, his answer is still useful to others (like myself). +1 for mshtml equivalent, saved me a question.
  • Kyeotic
    Kyeotic over 12 years
    For anyone that finds this, remove 'class' from the last line, should read ((HTMLHeadElement)head).appendChild((IHTMLDOMNode)scriptObje‌​ct); you will get errors otherwise.
  • Micah Smith
    Micah Smith over 12 years
    I appreciated this solution because it doesn't rely on the (albeit useful!) IHTMLSCriptElement assembly.
  • justin.m.chase
    justin.m.chase over 11 years
    Is 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
    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
    Chris Hobbs over 8 years
    I 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
    Khizar Iqbal over 6 years
    @justin.m.chase you saved my life.
  • gumuruh
    gumuruh almost 4 years
    is this applicable to inject jquery file also?