VB6中的集中式错误处理

VB6中的集中式错误处理,vb6,error-handling,Vb6,Error Handling,我有以下所有错误处理程序都调用的方法: Public Function ToError(strClass As String, strMethod As String) As String On Error GoTo errHandle ToError = "Err " & Err.Number & _ ", Src: " & Err.Source & _

我有以下所有错误处理程序都调用的方法:

Public Function ToError(strClass As String, strMethod As String) As String

    On Error GoTo errHandle

    ToError = "Err " & Err.Number & _
                      ", Src: " & Err.Source & _
                      ", Dsc: " & Err.Description & _
                      ", Project: " & App.Title & _
                      ", Class: " & strClass & _
                      ", Method: " & strMethod & _
                      ", Line: " & Erl

    Err.Clear

exitPoint:
   Exit Function

errHandle:
   oLog.AddToLog "Error in ToError Method: " & Err.Description, False
   Resume exitPoint
End Function
事实证明,由于我在此函数中声明了一个错误处理程序
On error GoTo errHandle
,VB6会在我能够记录错误之前清除该错误


有没有办法防止“On Error GoTo errHandle”语句清除错误?

您可以通过将Err对象的值作为参数传递到ToError中来解决问题。

On Error语句将始终清除
Err
变量(
Erl
也将重置为0)。理论上,这意味着您可以通过将
On Error
语句移动到
ToString=…
行下方(或者完全删除
ToError
函数中的错误处理程序)来解决问题,但不幸的是,这也不一定总是有效的

项目引用的每个组件(DLL、ActiveX EXE等)在内存中都有自己的
Err
实例。因此,如果您的
MainApp.exe
引发了一个传递到
ToError
的错误(例如,驻留在一个单独的
ErrorHandling.dll
中),则dll将看不到您的exe看到的
Err
变量。它们都有自己的私有
Err
变量

至少有两种方法可以解决这个问题:

方法1 同样,您可以向
ToError
函数添加其他参数,每个参数对应于需要访问的
Err
对象的每个属性

代码

Public Function ToError( _
   ByVal strErrSource As String, _
   ByVal nErrNumber As Long, _
   ByVal sErrDescription As String, _
   ByVal nLineNumber As Long) As String
Public Function ToError(ByVal oError As ErrObject, ByVal nLineNumber As Long) As String

   'Copy the important Err properties first, '
   'before doing anything else...            '

   Dim strErrSource As String
   Dim nErrNumber As Long
   Dim strErrDescription As String

   strErrSource = oError.Source
   nErrNumber = oError.Number
   strErrDescription = oError.Description

   On Error Goto errHandle

   'More code here
   '...
ToError Err, Erl
示例用法

Public Function ToError( _
   ByVal strErrSource As String, _
   ByVal nErrNumber As Long, _
   ByVal sErrDescription As String, _
   ByVal nLineNumber As Long) As String
Public Function ToError(ByVal oError As ErrObject, ByVal nLineNumber As Long) As String

   'Copy the important Err properties first, '
   'before doing anything else...            '

   Dim strErrSource As String
   Dim nErrNumber As Long
   Dim strErrDescription As String

   strErrSource = oError.Source
   nErrNumber = oError.Number
   strErrDescription = oError.Description

   On Error Goto errHandle

   'More code here
   '...
ToError Err, Erl
然后,您必须像这样从错误处理程序中调用,将当前
Err
对象中的所有相关值以及
Erl
一起传递给它:

ToError Err.Source, Err.Number, Err.Description, Erl 
如果您还想要
App.Title
,您还必须为
ToError
添加一个额外的参数,因为
App.Title
将等于定义
ToError
方法的项目的
App.Title
,而不是引发错误的组件。如果
ToError
在不同的项目中,这一点很重要

方法2 通过将
Err
对象本身作为参数传递给函数,您可以使
ToError
调用稍微不那么冗长,但是,在这种情况下,
ToError
函数应该做的第一件事是立即存储所需的所有相关属性的副本,因为后续的
On Error
语句将清除该变量

代码

Public Function ToError( _
   ByVal strErrSource As String, _
   ByVal nErrNumber As Long, _
   ByVal sErrDescription As String, _
   ByVal nLineNumber As Long) As String
Public Function ToError(ByVal oError As ErrObject, ByVal nLineNumber As Long) As String

   'Copy the important Err properties first, '
   'before doing anything else...            '

   Dim strErrSource As String
   Dim nErrNumber As Long
   Dim strErrDescription As String

   strErrSource = oError.Source
   nErrNumber = oError.Number
   strErrDescription = oError.Description

   On Error Goto errHandle

   'More code here
   '...
ToError Err, Erl
示例用法

Public Function ToError( _
   ByVal strErrSource As String, _
   ByVal nErrNumber As Long, _
   ByVal sErrDescription As String, _
   ByVal nLineNumber As Long) As String
Public Function ToError(ByVal oError As ErrObject, ByVal nLineNumber As Long) As String

   'Copy the important Err properties first, '
   'before doing anything else...            '

   Dim strErrSource As String
   Dim nErrNumber As Long
   Dim strErrDescription As String

   strErrSource = oError.Source
   nErrNumber = oError.Number
   strErrDescription = oError.Description

   On Error Goto errHandle

   'More code here
   '...
ToError Err, Erl

无法阻止
出错
清除错误

  • 您只需将错误处理从
    删除到错误
    。它是如此的短和平淡,它不可能经历一个错误
  • 最好重构错误处理,以便将此
    ToError
    代码内联到通用错误报告例程中,该例程执行日志记录或任何需要的操作。然后使用中的技术

顺便说一句,如果有人读到这篇文章是在手动添加错误处理程序,请停止您正在做的任何事情,并立即获得免费软件包。

您可以创建一个用户定义的类型,如下所示

Private Type TempErrObj
    ErrNumber As Integer
    ErrSource As String
    ErrDescription As String
End Type
稍后修改ToError函数,如下所示:

Public Function ToError() As String
    Dim iTempErr As TempErrObj
    iTempErr.ErrNumber = Err.Number
    iTempErr.ErrSource = Err.Number
    iTempErr.ErrDescription = Err.Description
    On Error GoTo errHandle

    ToError = "Err " & iTempErr.ErrNumber & _
                      ", Src: " & iTempErr.ErrSource & _
                      ", Dsc: " & iTempErr.ErrDescription & _
                      ", Project: " & App.Title & _
                      ", Line: " & Erl
    Err.Clear

exitPoint:
   Exit Function

errHandle:
    oLog.AddToLog "Error in ToError Method: " & Err.Description, False
   Resume exitPoint
End Function

在调用Error GoTo errHandler之前,在新实例中捕获Err对象。然后引用不起作用的新实例。@gooch。引用也被重置。VS 08在消除VB6异常方面做得相当好。;-)(p.s.只是diggin。我将VB从4.0编写到VS03。然后您可以尝试先检查Err==Nothing。然后为每个属性分配本地字符串/整数。+1。方法1实际上是我们使用的,尽管我们有一个集中式例程创建错误的字符串表示并记录它。
ToError
例程给出n如果你必须在错误字符串中传递每个要组装的项,那么问题中的n将毫无价值。@MarkJ:完全同意。理想情况下,该方法应该同时创建错误字符串并记录它,这样首先就值得拥有一个方法,而不必在任何需要的地方调用单独的日志代码。我们有一个集中的LogRuntimeError方法用于此目的。@MarkJ.On错误的要点是捕捉错误为null或访问错误属性导致错误的极不可能的情况。我从未见过这种情况,但我的应用程序是全天候的,所以我不能承担任何未处理的错误。这里的解决方案没有起作用。@angryHacker:不幸的是
On Error
被设计为总是清除当前
Err
变量。这就是它的工作方式。如果您想在
ToError
方法中保留
On Error
,唯一的实际选择是执行类似于方法1的操作,即显式地将所有错误属性传递给错误发生时的错误处理功能。无法避免错误上的
将清除
Err
的内容。