VBA 异常从处理程序中溜走

VBA Exception Slipping Through Handler

我继承了一个 hideous Excel VBA 应用程序,它是由一个显然不喜欢函数和注释的人编写的。打开源代码就像凝视着疯狂的深渊,9 级 地狱 缩进等待粗心者的陷阱。

首先,设置。

在调试间歇性问题的过程中,我确定了主要函数中的特定行作为其位置。由于异常对我来说修复起来并不容易,所以我给了这一行,而且只有这一行,一个显示自定义消息的错误处理程序。

    ' Lots of stuff cut out
    On Error GoTo TechReleaseBuildError
    lb_Err1 = BuildDirectories(gj_TechBld.mt_TechRlsOutDir)
    On Error GoTo 0
    ' Lots of stuff cut out
    Exit Sub
TechReleaseBuildError:
    MsgBox "Error building tech release. Pause the synchronization software and try again."
    Stop
    Resume
End Sub

StopResume 只是为了帮助调试,因为弹出的正常错误消息没有调试错误的选项。

BuildDirectories 函数中,我确定了导致错误的一行被踢到主要函数。我也在这个函数中放置了错误处理程序。

    ' Lots of stuff cut out
    Exit Function
TEST:
    Stop
    Resume

SynchroRetry:
    Dim CurrentError As ErrObject
    CurrentError = Information.err
    SynchroRetryCounter = SynchroRetryCounter + 1
    Debug.Print "Synchro Error, retrying #" + SynchroRetryCounter
    Stop
    If SynchroRetryCounter > 5 Then
        Stop
        Information.err.Raise CurrentError.Number, CurrentError.Source, CurrentError.Description, CurrentError.HelpFile, CurrentError.HelpContext
    Else
        Application.Wait Now + #12:00:03 AM#
        Resume
    End If

End Function

BuildDirectories 的最开始,我放置了一个 On Error GoTo TEST 语句作为一个包罗万象的错误处理程序,这样我就可以识别它们来自哪些行,并且还使用了 SynchroRetry 处理程序我已经知道的一行导致了一个问题,我立即将其重置回 TEST 处理程序。 SynchroRetry 处理程序只等待 3 秒并重试,在第 5 次重试后失败。

' For some reason, this line (and only this line so far) causes problems when synchronization software is running.
' The error handler waits for a few seconds then tries again a few times.
Dim SynchroRetryCounter As Integer
SynchroRetryCounter = 0
On Error GoTo SynchroRetry
lj_FSO.CopyFile Source:=lt_RPOFilePath & lt_RPOFileName, Destination:=lt_VinRposDir & "\" & lt_RPOFileName, OverWriteFiles:=True ' Trouble line
On Error GoTo TEST

我已经用 Find 验证了这些是函数中仅有的 3 个 On Error 语句(甚至是模块中的唯一语句)。除了显示的两个之外,顶层函数也没有 On Errors

简而言之,顶层函数只有一行有一个错误处理程序,它所包含的函数内部也有两个错误处理程序,一个是它已知的麻烦行之一,另一个是应该的一般错误处理程序涵盖整个功能。

问题是出现了导致我的 "Error building tech release." 消息显示的错误,但似乎没有触发 TEST 或 SynchroRetry 错误处理程序。我无法想象这怎么可能。我对 VBA 的错误处理模型的怪异还比较陌生,但我不认为我做错了什么。我在这里错过了一些微妙之处吗?异常如何能够绕过我的处理程序并像这样在堆栈中冒泡?我不相信函数值的分配或传递会导致问题,因为它们只是一个布尔值和字符串值。该问题也是间歇性的,仅当我们在此程序将文件复制到的目录上激活文件同步软件时才会出现。

所以在我发布这篇文章几个小时后,我设法弄明白了。

调试按钮不在错误框上的原因是因为在选项中错误陷阱设置为 "Break on Unhandled Error"。将其更改为 "Break in Class Module" 会使按钮恢复原状。

异常绕过我的错误处理程序的原因是它们发生在我的 SynchroRetry 错误处理程序中。特别是,我不得不更改前几行:

Dim CurrentError As ErrObject
CurrentError = Information.err
SynchroRetryCounter = SynchroRetryCounter + 1
Debug.Print "Synchro Error, retrying #" + SynchroRetryCounter

对此:

Dim CurrentError As New ErrObject
Set CurrentError = Information.err
SynchroRetryCounter = SynchroRetryCounter + 1
Debug.Print "Synchro Error, retrying #" + CStr(SynchroRetryCounter)

请注意添加的 NewSetCStr

问题已解决。