Доступ к объектам JavaScript с vb.net
Я работаю над приложением vb.net, которое взаимодействует с веб-приложением (предоставленным третьей стороной) для предоставления дополнительных функций (например, удаление пунктов меню, извлечение информации со страниц и т. Д.). Веб-приложение полностью управляется javascript, но размещается на asp.net и используется только с Internet Explorer.
Я пытаюсь прочитать свойства из объекта JavaScript и выполнить некоторые из его функций. Мне удалось заполучить объект javascript, получив mshtml.HTMLDocument из iframe, в котором находится скрипт, и используя следующий код:
Dim jsObject as Object
jsObject = htmldoc.Script.jsObject
jsObject существует как {System.__ComObject}, и я могу использовать его для выполнения любой из его функций или чтения его свойств следующим образом:
Dim value as String = jsObject.FunctionThatReturnsAString()
jsObject.FunctionTHatDoesSomethingInWebApp("Param1", "Param2")
Это прекрасно работает. Однако, когда я оставляю страницу / фрейм с jsObject и возвращаюсь к нему, тот же код вызывает исключение при повторном получении объекта javascript из фрейма (т. Е. При выполнении следующей строки):
jsObject = htmldoc.Script.jsObject
Исключение: участник не найден. (Исключение из HRESULT: 0x80020003 (DISP_E_MEMBERNOTFOUND))
Если я перестану отлаживать и перезапущу, он снова будет работать (пока я не покину страницу и т. Д.). Я не уверен, что происходит, из-за чего объект javascript исчезает, насколько это касается моего приложения. Я предполагаю, что это связано с тем, что мое приложение содержит ссылку на COM-объект, и мне нужно каким-то образом освободить его (в частности, поскольку у него есть базовый тип MarshalByRefObject - что имеет смысл, поскольку оно передается между доменами приложения).
Почему это происходит? Есть ли лучший способ доступа к объекту javascript, его свойствам и функциям?
1 ответ
Я нашел то, что в моем случае является лучшим способом достижения того, что мне нужно. Вместо того, чтобы обращаться к jsObject напрямую как к COM-объекту (и беспокоиться о маршалинге и т. Д.), Я либо использую:
- execScript для вызова функций без возвращаемого значения или
- создайте скрытый элемент div в кадре, в котором я работаю, установите innerHTML этого div равным любому возвращаемому значению переменной / функции javascript, которое мне интересно, используя execScript, а затем отдельно прочитайте это значение из DOM
Чтобы прочитать возвращаемую переменную / функцию, я использую следующую функцию vb.net:
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
Тогда я бы использовал эту функцию следующим образом (учитывая мой пример в исходном вопросе):
Dim value as String = getJScriptVariable("jsObject.FunctionThatReturnsAString()")
Чтобы выполнить код JavaScript без необходимости возвращать значение, я просто выполняю его следующим образом:
fMaster.execScript("jsObject.FunctionTHatDoesSomethingInWebApp('Param1', 'Param2')")
Мне все еще было бы интересно узнать, почему у меня раньше была проблема с невозможностью доступа к объекту javascipt после того, как я покинул страницу и вернулся, однако это решает мою проблему, поэтому я счастлив на данный момент! Я надеюсь, что это поможет кому-то еще в какой-то момент.