7

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 the 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 on 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)

5 Answers 5

8

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!

Sign up to request clarification or add additional context in comments.

2 Comments

Your answer would be more likely to help if you explained specifically what you did to solve the threading issue. :-)
BTW: As I have seen on some pages, Dispatcher.Invoke is from WPF. Do you have a solution for normal C# projects.
5

You have to access document.parentWindow in an STA thread. This may help you:

  private WebBrowser _webBrowser; //initialize this somewhere

  private void ExecuteJavaScript()
  {
     Thread aThread = new Thread(ExecuteJavaScriptWorker);
     aThread.SetApartmentState(ApartmentState.STA);
     aThread.Start(); 
  }

  private void ExecuteJavaScriptWorker()
  {
      HTMLDocument _document = _webBrowser.Document;
      _document.parentWindow.execScript("alert('Arbitrary javascript code')", "javascript");
  }

Comments

3

you can simple do:

ie.Navigate("javascript:" + jsScript);

where ie is your instance of internetexplorer

1 Comment

Very limited! in terms of what code you can execute!
1

This is an example of how to get Document of some page. It is close to the examples that shown above with the small (but important) difference - I am using method Navigate2 - this one works properly.

public static mshtml.HTMLDocument NavigateTo(String anUrl) {
  object locEmpty = 0;
  object locUrl = anUrl;
  SHDocVw.InternetExplorer _ie = new SHDocVw.InternetExplorer();
  _ie.Visible = true;
  _ie.Navigate2(locUrl, ref locEmpty, ref locEmpty, ref locEmpty, ref locEmpty);
  return(_ie.Document);
}   

This example will work for all pages that are opened by IE in Regular (Not Modal) Window. For modal windows (or modal dialogs), this example does not work.

Comments

0

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;

5 Comments

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?
(by that line I mean "mshtml.HTMLDocumentClass doc = (mshtml.HTMLDocumentClass)ie.Document;"
Did you add a reference to Microsoft.mshtml in your references? (not the Interop) It is under the list of .net references.
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!
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?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.