Microsoft KB Archive/269797

From BetaArchive Wiki
Knowledge Base


Article ID: 269797

Article Last Modified on 7/1/2004



APPLIES TO

  • Microsoft Transaction Services 1.0
  • Microsoft Transaction Services 2.0
  • Microsoft COM+ 1.0
  • Microsoft Visual Basic 6.0 Enterprise Edition



This article was previously published under Q269797

SUMMARY

When you create applications that use Component Object Model (COM) components, it is good design to write robust error handlers. Error handlers that are rich with information save hours of development time in which the developer must fix errors that occur. Ideally, each procedure within a component should have an error handler.

MORE INFORMATION

Client applications can create COM components and call methods on the component. The called component may call other methods within the component or possibly create another component. At run time, if an error occurs in any of these methods, it helps to know which method raised the error.

When you create an error handler, make no assumptions about the client that calls the method. After you catch (trap) the error (and optionally write it to a log), the error should be raised to the calling procedure.

If the code in the procedure manually raises an error, a custom error number should be defined as vbObjectError + customErrorNumber:

If (ReturnValue = 0) Then
    Call Err.Raise((vbObjectError + customErrorNumber), 
    "ProjectName.ModuleName.MethodName", "Return Value Is Zero")
End If
                

Sample Code

The code to follow is from a Visual Basic .cls module with error handling that writes to the Event Log at runtime. This example also demonstrates how to build a "call stack" within the error handler.

In the example, a client that instantiates an instance of this object calls the ProcedureA property, which in turn calls the ProcedureB property, which in turns calls the ProcedureC property. ProcedureC then causes an error in code that is trapped by the error handler.

The Err.Description property of the error object that is raised to the client indicates the method in which the error occurred and the procedures that were called prior to the error occurring. With this information, you can easily find the offending code.

Public Sub ProcedureA()
On Error GoTo ehProcedureA:

    Call ProcedureB

Exit Sub

ehProcedureA:

Dim strErrDesc As String, strErrSource As String
Dim strErrNumber As String, strExtraInfo As String

    strExtraInfo = "ExtraInfo: ProcedureA being called."
    strErrDesc = Err.Description & vbCrLf & strExtraInfo
    strErrNumber = CStr(Err.Number)
    strErrSource = Err.Source & vbCrLf & "Procedure is ProcedureA"
    
    App.LogEvent vbCrLf & vbCrLf & _
                 "Description: " & strErrDesc & vbCrLf & vbCrLf & _
                 "Number: " & strErrNumber & vbCrLf & vbCrLf & _
                 "Source: " & strErrSource & vbCrLf & vbCrLf & _
                 "ThreadID: " & CStr(App.ThreadID), vbLogEventTypeError
                 
    Call Err.Raise(Err.Number, strErrSource, strErrDesc)

End Sub
Public Sub ProcedureB()
On Error GoTo ehProcedureB:

    Call ProcedureC

Exit Sub

ehProcedureB:

Dim strErrDesc As String, strErrSource As String
Dim strErrNumber As String, strExtraInfo As String

    strExtraInfo = "ExtraInfo: ProcedureB being called."
    strErrDesc = Err.Description & vbCrLf & strExtraInfo
    strErrNumber = "Number: " & CStr(Err.Number)
    strErrSource = Err.Source & vbCrLf & "Procedure is ProcedureB"

    App.LogEvent vbCrLf & vbCrLf & _
                 "Description: " & strErrDesc & vbCrLf & vbCrLf & _
                 "Number: " & strErrNumber & vbCrLf & vbCrLf & _
                 "Source: " & strErrSource & vbCrLf & vbCrLf & _
                 "ThreadID: " & CStr(App.ThreadID), vbLogEventTypeError
                 
    Call Err.Raise(Err.Number, strErrSource, strErrDesc)
                     
End Sub
Public Sub ProcedureC()
On Error GoTo ehProcedureC:
Dim intDivByZero As Integer

    intDivByZero = 1 / 0

Exit Sub

ehProcedureC:

Dim strErrDesc As String, strErrSource As String
Dim strErrNumber As String, strExtraInfo As String

    strExtraInfo = "ExtraInfo: ProcedureC being called."
    strErrDesc = Err.Description & vbCrLf & strExtraInfo
    strErrNumber = "Number: " & CStr(Err.Number)
    strErrSource = Err.Source & vbCrLf & "Procedure is ProcedureC"

    App.LogEvent vbCrLf & vbCrLf & _
                 "Description: " & strErrDesc & vbCrLf & vbCrLf & _
                 "Number: " & strErrNumber & vbCrLf & vbCrLf & _
                 "Source: " & strErrSource & vbCrLf & vbCrLf & _
                 "ThreadID: " & CStr(App.ThreadID), vbLogEventTypeError
                 
    Call Err.Raise(Err.Number, strErrSource, strErrDesc)
        
End Sub
                

The Event Viewer Application log contains the error that was logged. The strExtraInfo section can contain either values of variables or the present state of the application.

REFERENCES

For additional information, click the article number below to view the article in the Microsoft Knowledge Base:

243548 INFO: Design Guidelines for VB Components Under ASP


Keywords: kbhowto kbbug kbdebug KB269797