views:

112

answers:

2

I'm using

SHDocVw.InternetExplorer ie = new SHDocVw.InternetExplorer()

to control/automate an instance of internet explorer. On certain pages I'd like to run a javascript function (init()). It seems the best way to do this is to use an HtmlDocument's InvokeScript method and I've been trying the following with no luck:

void ie_DocumentComplete(object pDisp, ref object URL)
{
  System.Windows.Forms.HtmlDocument doc = ie.Document;
  doc.InvokeScript("init");
}

Which fails because 'doc' is null. I can't seem to get a System.Windows.Forms.HtmlDocument from ie.Document. Besides trying to above, I've also tried:

System.Windows.Forms.HtmlDocument doc2 = (System.Windows.Forms.HtmlDocument)ie.Document;

and

System.Windows.Forms.HtmlDocument doc2 = ie.Document as System.Windows.Forms.HtmlDocument;

Any ideas how I can get this to work - or an even better way to run scripts on the page?

Thanks!!

EDIT:

Another way to run a javascript function appears to be:

SHDocVw.InternetExplorer ie = new SHDocVw.InternetExplorer()
mshtml.HTMLDocument doc = ie.Document;
mshtml.IHTMLWindow2 win = doc.parentWindow as mshtml.IHTMLWindow2;
win.execScript("init();", "javascript");

But the line

mshtml.IHTMLWindow2 win = doc.parentWindow as mshtml.IHTMLWindow2;

throws an error that it is an invalid cast (InvalidCastException) - even though IntelliSense (and msdn) say doc.parentWindow is a IHTMLWindow2. Any ideas? (Also I've made sure a page has been fully loaded before running that code)

A: 

The SHDocVw.InternetExplorer.Document is of type mshtmlHTMLDocumentClass, so you need to reference Microsoft.mshtml

mshtml.HTMLDocumentClass doc = (mshtml.HTMLDocumentClass)ie.Document;

The ie object also has to navigate somewhere for the document to have a value. such as

object test = new object();
ie.Navigate("c:\\tmp\\test1.html", ref test, ref test, ref test, ref test);

Total init:

SHDocVw.InternetExplorer ie = new SHDocVw.InternetExplorer();
object test = new object();
ie.Navigate("c:\\tmp\\test1.html", ref test, ref test, ref test, ref test);
mshtml.HTMLDocumentClass doc = (mshtml.HTMLDocumentClass)ie.Document;
Jack B Nimble
Thanks for your answer, but I'm having trouble getting that line to work. It's giving the following compiler error: "Interop type 'mshtml.HTMLDocumentClass' cannot be embedded. Use the applicable interface instead." Any ideas?
Evan
(by that line I mean "mshtml.HTMLDocumentClass doc = (mshtml.HTMLDocumentClass)ie.Document;"
Evan
Did you add a reference to Microsoft.mshtml in your references? (not the Interop) It is under the list of .net references.
Jack B Nimble
Yeah I have the reference. I've been able to control the explorer window and open new pages, just not run scripts. I am using C# 4.0 though, could that have anything to do with it? I only ask because it changes a few things with COM (like being able to call ie.Navigate with out having to fill out the extra params). Thanks again man!
Evan
It sort of does have to do with C# 4.0 - you can't use HTMLDocumentClass when mshtml is embedded. However I set the embedding value to false so I could run the above code and I wasn't able to convert from HTMLDocumentClass to Windows.Forms.HTMLDocument so I could use InvokeScript(). Any ideas?
Evan
A: 

The problem had to do with threading - I've wasted so much time with STA issues you'd think I'd learn by now :).

Anyhow I found a way to get the second bit of code I posted working and running javascript functions in the IE window! Here is the code:

this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
                {

                        mshtml.HTMLDocument doc = ie.Document;

                        mshtml.IHTMLWindow2 win = doc.parentWindow as IHTMLWindow2;
                        win.execScript("init();", "javascript");


                }));

Hope it helps someone!

Evan
Your answer would be more likely to help if you explained specifically what you did to solve the threading issue. :-)
EricLaw -MSFT-