我们有一个ActiveX组件,它通过SHDocVw在Internet Explorer窗口中显示一个网页。在DocumentComplete事件处理程序中,我们尝试从页面上的一个控件中检索值。我们知道控件在页面上(通过Fiddler跟踪可见)。
正是在这一点上事情变得不稳定。我们在运行时收到以下错误消息:
Error Message:
Public member 'elements' on type 'DBNull' not found.
Error Routine Location:
at Microsoft.VisualBasic.CompilerServices.Symbols.Container.GetMembers(String& MemberName, Boolean ReportErrors)
at Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateGet(Object Instance, Type Type, String MemberName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack)
at Foo.AddinModule.m_internetExplorer_DownloadComplete(Object pDisp, Object& url)
Error Source:
Microsoft.VisualBasic
Error Site Location:
System.Reflection.MemberInfo[] GetMembers(System.String ByRef, Boolean)
令人讨厌的代码行是这一行:
Me.IEInstance.Document.forms("frmRedirect").elements("redirectData").Value = outlookXML.OuterXml
因此,基本上,Me.IEInstance.Document.forms("frmRedirect")
正在评估DBNull
。
我们已经消除了区分大小写的问题。尝试在页面内移动控件,并验证HTML格式正确。我不知道为什么会这样。生成的HTML示例如下所示。
任何人都可以为此问题提出原因和解决方法吗?我现在正在接受任何建议。
HTML示例
<form id='frmRedirect' name='frmRedirect' action='pw_outlook/choosecontacts.aspx' method='POST'>
<input type='hidden' name='redirectData'>
</form>
更新2012年3月28日
我们已确定代码在某些配置下运行正常。然后,神秘的是,如果您按如下方式更改代码,它将成功某些用户:
Me.IEInstance.Document.forms("frmRedirect").Elements("redirectData").Value = outlookXML.OuterXml
^
^
也就是说,如果您只是更改Elements
的大小写。对我而言,在COM vtable查找过程中,这个问题很明显,但神秘之处在于并不是每个人都会遇到这种问题。只是一些用户。
另请注意,.forms("frmRedirect")
返回的表单是有效对象;但是,它似乎没有elements()
方法。
答案 0 :(得分:5)
您正在与DLR中的错误作斗争,DLR是在.NET 4中添加的动态语言运行库。堆栈跟踪上的代码与DLR的VB.NET绑定程序相关。这个错误几乎肯定不是由您发布的代码触发的,很可能是您项目中的某些其他代码使用dbase查询执行某些操作。鉴于异常消息中存在DBNull。
您需要Microsoft的支持才能深入了解这一点。他们需要你的项目给他们一个repro来工作,因为代码片段本身不会帮助他们找到它。您可以与Microsoft支持部门联系以启动它。他们会从你的信用卡中取出一大块,但你几乎肯定会把它拿回来,因为它可能是他们代码中的错误而不是你的错误。
此特定故障可能有一种解决方法,但并不能完全保证DLR损坏不会在以后引起某种问题。通过编写早期绑定代码,您可以在不使用DLR的情况下编写完全相同的代码。从Project + Add Reference,Browse选项卡开始,选择c:\ windows \ system32 \ mshtml.tlb
然后将您的代码段重写为:
Dim doc = DirectCast(Me.IEInstance.ActiveXInstance, mshtml.IHTMLDocument2)
Dim form = DirectCast(doc.forms("frmRedirect"), mshtml.IHTMLFormElement)
If form IsNot Nothing Then
Dim elem = DirectCast(form.elements("redirectData"), mshtml.IHTMLInputElement)
If elem IsNot Nothing Then
elem.value = outlookXML.OuterXml
End If
End If
答案 1 :(得分:0)
以下表达式评估为什么?
Me.IEInstance.Document.forms
Me.IEInstance.Document.forms("frmRedirect")
Me.IEInstance.Document.forms(0)
我不知道表单集合可以按名称编制索引,但也许我错了。请验证所有表达方式。
ActiveX控件与您的问题有什么关系?看来你的问题只是关于违规的代码行。我错了吗?
编辑:这是一种解决方法:为隐藏输入分配ID并按ID获取输入元素。
答案 2 :(得分:0)
试图帮助那些看着同样问题的人...... 多年来我一直在筛选库存数据。我喜欢看到正在被删除的网页,因为它使调试更加容易 我运行Windows 7 64位,Visual Studio 2010.当我的计算机自动更改为IE9时 - 我开始遇到很多问题已经运行多年的代码。 VB.NET中的代码如下:
Public WithEvents MyExplorer As SHDocVw.InternetExplorer
MyExplorer.Navigate("SomeURL")
While (MyExplorer.ReadyState <> SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE)
Application.DoEvents()
Thread.Sleep(500)
End While
Dim strHtml As String
strHtml = MyExplorer.Document.DocumentElement.innerHTML.Replace("&", "&").replace(" ", " ")
自IE9问世以来,我不得不进行两项重大更改: 1. MyExplorer.ReadyState&lt;&gt; SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE 2. MyExplorer.Document.DocumentElement.innerHTML
在第一种情况下,我正在做类似的事情 而(MyExplorer.Document.readyState&lt;&gt;“完成”) 这似乎不再可靠。我改为: while(MyExplorer.ReadyState&lt;&gt; SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE) 这似乎更可靠
在第二种情况下,我使用以下方式获取网页的HTML:
MyExplorer.Document.documentElement.innerhtml
虽然MyExplorer.ReadyState已经完成,但我仍然遇到异常 - documentElement为null(或DBNull)。有趣的是,在Intellisense和Visual Studio的“局部变量”中,我可以看到documentElement和innerhtml。
基于我在上面的一个答案中看到的内容 - 我只是改变了DocumentElement的大写,现在它似乎可靠地工作了
VB.NET的巨大优势在于它假设不区分大小写......