【问题标题】:Confusing index out of bounds in shapes collection形状集合中的混淆索引越界
【发布时间】:2019-10-22 05:41:23
【问题描述】:

我正在尝试修复一些使用 MS Office 互操作库的 VB NET 代码中的不一致问题。使用相同的文件和数据运行,下面的代码会抛出这个异常:

指定集合的​​索引超出范围。
在 System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
在 System.Runtime.InteropServices.CustomMarshalers.EnumeratorViewOfEnumVariant.MoveNext()
在 path\file.vb:line 1454 中的 myProject.TableNotePages(clsUsrDoc& usrdoc)
...

第 1454 行是 iShp += 1 行

Dim MyDoc As Word.Document = usrdoc.Document
Dim NoteBoxes As New Collections.Generic.SortedDictionary(Of Integer, Word.TextFrame)
Dim iShp As Integer = 1
For Each shp As Word.Shape In MyDoc.Sections.First.Headers(Word.WdHeaderFooterIndex.wdHeaderFooterPrimary).Shapes
    If Not shp.TextFrame.Next Is Nothing Then
        NoteBoxes.Add(iShp, shp.TextFrame)
        iShp += 1
    End If
Next

有几个问题可以帮助我解决这个问题:

  1. 为什么不是每次都这样?
  2. 跟踪中的框架 moveNext 方法是否在循环的最后一个非条件行而不是“for each”或“next”行上调用(在 iShp += 1 和 End If 之间添加另一行会导致它而是在那条线上失败)?
  3. VB foreach 循环(我的专长更多是 C/Java)或互操作集合是否有一些不寻常的地方会导致它尝试迭代超出形状集合的末尾?

感谢您对此处可能发生的情况的任何见解。

【问题讨论】:

  • 你能把 yoru ForEach 改成 For 循环吗?过去我遇到过互选问题,不记得为什么。但这样做会给我一个更有用的不同错误。
  • iShp += 1 真的不应该引发异常。它必须在两行之后发生......
  • @the_lotus 是的,这是我尝试的下一件事。到目前为止,似乎还可以。我还没有看到足够多的东西来相信它总是没问题的,而且这种行为仍然令人担忧。
  • @djv 我同意。在此之后添加另一行会将行更改为添加的行,因此它不会被某些行数关闭。我最好的猜测是 VB NET / VS2013 编译的方式导致迭代在最后一个非结构(不在 END IF 上)行之后立即发生,因此在该行上报告了异常。希望有人可以证实或反驳这一点,尽管更有趣的问题是为什么会抛出异常。
  • @codemonk 这可能就是线路中断的原因。编译为 Debug 时是否会出现此问题?

标签: vb.net visual-studio-2013 ms-word office-interop


【解决方案1】:

似乎有时 vb/word 互操作会任意离开形状集合的末尾。下面的代码将“for each”替换为“for x to y”,在几个环境中成功运行了统计上显着的次数(大约 50 次)。我知道这不是一个好的答案,并且仍然没有回答为什么会发生这种情况的问题,但确实解决了问题,因此发布作为答案以防示例对其他人有帮助:

    Dim MyDoc As Word.Document = usrdoc.Document
    Dim NoteBoxes As New Collections.Generic.SortedDictionary(Of Integer, Word.TextFrame)
    Dim iShp As Integer = 1
    Dim loopLength As Integer = MyDoc.Sections.First.Headers(Word.WdHeaderFooterIndex.wdHeaderFooterPrimary).Shapes.Count
    Dim shp As Word.Shape = Nothing
    For i As Integer = 1 To loopLength '1-indexed
        shp = MyDoc.Sections.First.Headers(Word.WdHeaderFooterIndex.wdHeaderFooterPrimary).Shapes(i)
        If Not shp.TextFrame.Next Is Nothing Then
            NoteBoxes.Add(iShp, shp.TextFrame)
            iShp += 1
        End If
    Next

【讨论】:

  • shp 的 Dim 应该移到 For 循环的范围内。否则之前的 shp 值将在下一次迭代中保持不变。 stackoverflow.com/questions/32619430/…
  • @вʀaᴎᴅᴏƞвєнᴎєƞ 该值持续存在不是问题。即使在这种情况下可能微不足道,我也不会在每次迭代中产生初始化与分配的成本。 SO 链接中的 MSDN 链接(docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/…)(为什么不直接链接?)表明每次都对其进行初始化是“明智的”,并且对我来说就像一个风格建议。这与这里发生的任何事情都无关紧要。
猜你喜欢
  • 2016-06-10
  • 2011-07-31
  • 2019-05-13
  • 2021-07-13
  • 1970-01-01
  • 1970-01-01
  • 2017-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多