views:

302

answers:

3

We are developing an application which needs to interact with the active document in IE.

Context: The app is a C#, .Net 3.5 desktop app. The goal is to highlight specific text elements in the web page on user request. For this we need to retrieve and interpret web page elements (the need for the return value) then act on them through another JS call. The operations that must be made in the web page are not all done at the same time so we must get some kind of "snapshot" of the interesting text elements (we do this on the Mac version of our app by returning a string containing an XML representation of those elements).

In .Net we used IHTMLDocument2's execScript method successfully to run some JavaScript inside the active IE document, but we can't seem to find a way to get a return value from the call. Based on the doc execScript returns an execution success/failure constant which is not what we need.

In essence what we need to do is to load some JavaScript from a text file into a string, then send it to IE for execution. Then we need to get a string back from the called script.

Any hints on what objects to use? How to proceed to get this functionality?

Thanks in advance!

My colleague found the solution, based on what Alun Harford said:

string jsToRun = "function myTest() { return document.title; } myTest();";
mshtml.IHTMLDocument2 myIHTMLDocument2 = GetSelectedIEWindow();
IE ie = IE.AttachToIE(Find.ByUrl(myIHTMLDocument2.url));
string jsReturn = ie.Eval(jsToRun);

jsReturn then contains the string value returned from myTest() in JavaScript. Note that there is no return before the myTest() function call in the script!

+1  A: 

If you are providing the html and script yourself you can do the following:

  • execute the javascript function
  • let the js function place the result in an html element
  • wait till the function is done running
  • retrieve the html element using document.getElementById
  • and retrieve the value

I'm not sure if there's a easier way to do this.

Niek H.
Unfortunately the goal of the app is to highlight text in existing web pages on request by the user when they browse the Web. So I need to be able to send my JS code from the .Net desktop app, have IE run it, then get the return the string value from the function that was ran.
Form
You can add a hidden element using document.write or some other function. And then use that element in your javascript code.
Niek H.
I see what you mean but what I need is a method or object in .Net to retrieve the return value (or the hidden element's value) in question.
Form
Use HtmlElement element = m_webBrowser.Document.GetElementById("[ID]") and then element.InnerHtml or element.GetAttribute("[AttributeName]") depends on what you want to use
Niek H.
+1  A: 

Have a look at the WatiN codebase. In there, IE.Eval does exactly what you're looking for.

Alun Harford
That did the job! It's very easy to use too. See my original question for the code.
Form
A: 

Well it is nasty but it can be done.

Try this:

    [Guid("626FC520-A41E-11CF-A731-00A0C9082637"), InterfaceType(ComInterfaceType.InterfaceIsDual)]
    interface IHTMLDocument
    {
        void Script([Out, MarshalAs(UnmanagedType.Interface)] out object ppScript);
    }

    public object RunScript(InternetExplorer ie, string scriptText)
    {                        
        IHTMLDocument doc = (IHTMLDocument)ie.Document;
        object scriptObj;
        doc.Script(out scriptObj);

        Type t = scriptObj.GetType();
        return t.InvokeMember("eval", System.Reflection.BindingFlags.InvokeMethod, null, scriptObj, new object[] { scriptText });            
    }

That will return your value in the object (just cast to what ever type you expected). Of course .NET 4 makes this even easier ;)

tyranid