Question

I'm working on a vb.net application that interacts with a (third party provided) web app to provide additional functionality (e.g. removing menu items, pulling information from the pages, etc.). The web app is completely driven by javascript but is hosted in asp.net and is only used with Internet Explorer.

I'm trying to read properties from a javascript object and execute some of it's functions. I've managed to get hold of the javascript object by getting the mshtml.HTMLDocument of the iframe the script resides in and using the following code:

Dim jsObject as Object
jsObject = htmldoc.Script.jsObject

jsObject exists as a {System.__ComObject} and i can use it to execute any of it's functions or read it's properties as follows:

Dim value as String = jsObject.FunctionThatReturnsAString()
jsObject.FunctionTHatDoesSomethingInWebApp("Param1", "Param2")

This works great. However, when I leave the page/frame with jsObject in and return to it, the same code throws an exception when getting the javascript object from the frame again (i.e. executing the following line):

jsObject = htmldoc.Script.jsObject

Exception: Member not found. (Exception from HRESULT: 0x80020003 (DISP_E_MEMBERNOTFOUND))

If I stop debugging and restart, it works again (until i leave the page, etc.). I'm not sure what's happening that's causing the javascript object to disappear as far as my app's concerned. I'm presuming it's due to my app holding a reference to the COM object and i need to release it in some way (particulary as it's got a base type of MarshalByRefObject - which makes sense as it's being passed between app domains).

Why is this happening? Is there a better way of accessing a javascript object, it's properties and functions?

Was it helpful?

Solution

I've found what is, in my case, a better way of achieving what I need. Instead of accessing the jsObject directly as a COM Object (and worrying about Marshaling, etc.), I either use:

  • execScript to call functions with no return value or
  • create a hidden div element in the frame i'm working in, set the innerHTML of that div equal to whatever javascript variable/function return value that i'm interested in using execScript and then read that value seperately from the DOM

To read a variable/function return i use the following vb.net function:

Private Function getJScriptVariable(ByVal JScript As String)
    Dim command As New StringBuilder()
    command.Append("var e = document.getElementById('Matt_JScriptReturn');")
    command.Append("if (e == null) {")
    command.Append("var e = document.createElement('div');")
    command.Append("e.id = 'Matt_JScriptReturn';")
    command.Append("e.type = 'hidden';")
    command.Append("document.body.appendChild(e);")
    command.Append("}")
    command.Append("e.innerHTML = ")
    command.Append(JScript)
    command.Append(";")

    'fMaster is the frame containing the javascript's mshtml.IHTMLWindow2
    fMaster.execScript(command.ToString(), "JScript")

    'N.B. fMaster_Document is the fMaster's mshtml.HTMLDocument
    Return fMaster_Document.getElementById("Matt_JScriptReturn").innerHTML

    'Optionally execScript to remove element from DOM at this point
End Function

Then i would use that function as follows (respecting my example in the original question):

Dim value as String = getJScriptVariable("jsObject.FunctionThatReturnsAString()")

To execute javascript code without needing to return a value I simply execute it as follows:

fMaster.execScript("jsObject.FunctionTHatDoesSomethingInWebApp('Param1', 'Param2')")

I'd still be interesting in finding out why i had the problem earlier with the javascipt object being unable to access after leaving the page and returning, however this solves my problem so i'm happy for now! I hope this helps someone else at some point.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top