views:

11135

answers:

9

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?

A: 

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. :)

mattlant
ASP.Net doesn't have much to do with scripting the WebBrowser control in a winforms app.
jsight
I will leave this up here for the punishment i deserve ;)
mattlant
I probably would have under-read the same way and given the same incorrect answer
Grank
at least i am not alone ;)
mattlant
I interpreted it the same way...
Turnkey
A: 

You can always use a "DocumentStream" or "DocumentText" property. For working with HTML documents I recommend a HTML Agility Pack.

TcKs
Nice tip... I'm sure that lib will come in handy at some point.
jsight
A: 

You can use the HTMLGenericControl to do this, e.g.

HtmlGenericControl Include = new HtmlGenericControl("script");
Include.Attributes.Add("type", "text/javascript");
Include.InnerHtml = "alert('JavaScript in Page Header');";
this.Page.Header.Controls.Add(Include);
Turnkey
+3  A: 

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

ZeroBugBounce
Nice... this together with the tips provided by korchev works perfectly. I wish I could set two accepted solutions on this one. :)
jsight
+9  A: 

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");
korchev
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.
ZeroBugBounce
What about adding a reference to a local js file? Please see http://stackoverflow.com/questions/4029602/how-do-i-add-a-local-script-file-to-the-html-of-a-webbrowser-control
IAmAN00B
+1  A: 

Hi,

I need to inject script, but I don't have half of the methods discussed in .Net 3.5 WPF WebBrowser control.

For example, I do not have: - browserCtrl.Document.GetElementsByTagName - head.AppendChild - se.DomElement;

I need to do all in WPF. So far I tried

        mshtml.HTMLDocument doc2 = webBrowser.Document as mshtml.HTMLDocument;
        mshtml.IHTMLHeadElement head = doc2.getElementsByTagName("head") as mshtml.IHTMLHeadElement;
        mshtml.IHTMLElement se = doc2.createElement("script") as mshtml.IHTMLElement;
        mshtml.IHTMLScriptElement element = (mshtml.IHTMLScriptElement)se.document;
        element.text = "alert('here we are')";
        // head.AppendChild( se ) <-- No such method

with no luck.

Do you have the similar example for WPF WebBrowser control?

+3  A: 

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.

Eyal
A: 

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);
justin.m.chase
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.
alimbada
A: 

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);
camilin87
two years late I'm afraid
camilin87