未找到类型“DBNull”上的公共成员“元素”

时间:2012-02-21 21:55:57

标签: .net internet-explorer activex

我们有一个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()方法。

3 个答案:

答案 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("&amp;", "&").replace("&nbsp;", " ")

自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的巨大优势在于它假设不区分大小写......