vb.netmshtmldommarshalbyrefobjectcomobject

Accessing JavaScript Objects from vb.net


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?


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:

    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.