visualexp
asked on
Errors propagation
Is there any way to propagate the error handling from a class module (Class1) to an other class module (Class2) using the first one? I would like to trap the error (on error goto...) in Class2 even if the error is generated in Class1.
In order to be clearer I'm writing you an example of the code of the two classes:
CLASS1:
Public Function OpenRs(query As String) As ADODB.Recordset
Dim Rs As New ADODB.Recordset
Rs.Open query, conn, adOpenKeyset, adLockBatchOptimistic
Set openRs = Rs
End Function
'------------------------- ----------
CLASS2:
Dim oClass1 As New Class1
Public Sub ManagingRs()
dim Rs as AdODB.Recorset
ON ERROR GOTO ESC:
set RS=oClass1.OpenRs
Exit sub
ESC:
msgbox err.description
End Sub
'------------------------- ---------- ---
If an error occurs in CLASS1, I've noticed that the execution of the program is stopped at the CLASS1 level even if the error handling is in CLASS2.
Thank you in advance
In order to be clearer I'm writing you an example of the code of the two classes:
CLASS1:
Public Function OpenRs(query As String) As ADODB.Recordset
Dim Rs As New ADODB.Recordset
Rs.Open query, conn, adOpenKeyset, adLockBatchOptimistic
Set openRs = Rs
End Function
'-------------------------
CLASS2:
Dim oClass1 As New Class1
Public Sub ManagingRs()
dim Rs as AdODB.Recorset
ON ERROR GOTO ESC:
set RS=oClass1.OpenRs
Exit sub
ESC:
msgbox err.description
End Sub
'-------------------------
If an error occurs in CLASS1, I've noticed that the execution of the program is stopped at the CLASS1 level even if the error handling is in CLASS2.
Thank you in advance
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
If you are operating in an MTS environment, it important to make sure the error code has the vbObjectError constant added. COM will not propogate the error properly if you do not.
To achieve this, simply put error handling in your class module (class2) that looks like this:
IF Err.Number <> 0 THEN
Err.Raise Err.Number Or vbObjectError, Err.Source, Err.Description
END IF
To achieve this, simply put error handling in your class module (class2) that looks like this:
IF Err.Number <> 0 THEN
Err.Raise Err.Number Or vbObjectError, Err.Source, Err.Description
END IF
Anthony, can you explain that a bit further?
The use of vbObjectError for COM/Automation objects is mentioned in heaps of places, but rarely with an explanation - i.e. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odeopg/html/deconerrorhandlinginclassmodules.asp
Basically, the return value from a COM object (even in VB) is called a HRESULT. Various bits in the HRESULT mean various things, and 'Or' ing the "real" error code with vbObjectError sets the bits that tell MTS that the result is a COM error.
To "decode" the error at the other end (the handler), use Err.Number AND NOT vbObjectError.
Basically, the return value from a COM object (even in VB) is called a HRESULT. Various bits in the HRESULT mean various things, and 'Or' ing the "real" error code with vbObjectError sets the bits that tell MTS that the result is a COM error.
To "decode" the error at the other end (the handler), use Err.Number AND NOT vbObjectError.
I found a reference that explains HRESULTS better - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mapi/html/_mapi1book_error_handling.asp
<ping>
Try this way...
CLASS1:
Public Function OpenRs(query As String, ByRef Rs As Variant) As Variant
On Error GoTo ESC:
Dim col As New Collection
Dim Rs As New ADODB.Recordset
Rs.Open query, conn, adOpenKeyset, adLockBatchOptimistic
Set openRs = Rs
col.Add False, Key:="ERROR"
Set OpenRs= col
Exit Function
ESC:
col.Add True, Key:="ERROR"
col.Add Err.Description, Key:="MSG"
Set OpenRs = col
End Function
CLASS2:
Dim oClass1 As New Class1
Public Sub ManagingRs()
ON ERROR GOTO ESC:
dim Rs as AdODB.Recorset
Dim col As New Collection
dim strQuery as String
strQuery = " SELECT * FROM TABLENAME ..... "
set col=oClass1.OpenRs(strQuer y,Rs)
if col("ERROR") then
Err.Raise
end if
Exit sub
ESC:
msgbox err.description
End Sub
CLASS1:
Public Function OpenRs(query As String, ByRef Rs As Variant) As Variant
On Error GoTo ESC:
Dim col As New Collection
Dim Rs As New ADODB.Recordset
Rs.Open query, conn, adOpenKeyset, adLockBatchOptimistic
Set openRs = Rs
col.Add False, Key:="ERROR"
Set OpenRs= col
Exit Function
ESC:
col.Add True, Key:="ERROR"
col.Add Err.Description, Key:="MSG"
Set OpenRs = col
End Function
CLASS2:
Dim oClass1 As New Class1
Public Sub ManagingRs()
ON ERROR GOTO ESC:
dim Rs as AdODB.Recorset
Dim col As New Collection
dim strQuery as String
strQuery = " SELECT * FROM TABLENAME ..... "
set col=oClass1.OpenRs(strQuer
if col("ERROR") then
Err.Raise
end if
Exit sub
ESC:
msgbox err.description
End Sub
a small mistake in CLASS 2:
ESC:
msgbox col("MSG")
End Sub
ESC:
msgbox col("MSG")
End Sub
Hello experts ! I had a similar problem some time ago:
I wrote an OCX and used it in an EXE. When an error
occurred in the OCX (especially in an event of the OCX-class) i would be able to stop all program execution in the ocx. The decision shold be made in the EXE, because we plan to distrubute the OCX to other clients.
Because you sholudn't force a Server (the OCX) to shut down (vb cares of it, just shut down all clients so that the counter of references becomes 0).
In my case i used to copy the error object and pass it to a public error-event which could be handled in the exe.
'------------------------- ---------- ---------- ---------- --
Public Event Error(ErrorInfo As vbpCloneErr.typGtwErrInfo)
Public Function ClosePopUp() As AmbientProperties
On Error GoTo hErr
'_________________________ __________ __________ __________ __________ __________ __________ __________ __________ ______
.........
'_________________________ __________ __________ __________ __________ __________ __________ __________ __________ ______
Exit Function
hErr:
Select Case Err
Case Else
If Not ExitForever Then
Call ErrCloner.Copy(ExtErrInfo, TMPErrInfo, Err, Erl)
Call SetExtErrInfo(TMPErrInfo, "vbpGtwCombo", "gtwCombo", "ClosePopUp", "Function", "{ControlName}")
Call SafeClosePopup
RaiseEvent Error(ExtErrInfo)
Select Case ExtErrInfo.ToDo
Case enmNoResponse
Call ShowError(ExtErrInfo)
Case enmResume
Resume
Case enmResumeNext
Resume Next
Case enmExitSub
Exit Function
Case enmEnd
ExitForever = True
Exit Function
End Select
End If
End Select
End Function
I wrote an OCX and used it in an EXE. When an error
occurred in the OCX (especially in an event of the OCX-class) i would be able to stop all program execution in the ocx. The decision shold be made in the EXE, because we plan to distrubute the OCX to other clients.
Because you sholudn't force a Server (the OCX) to shut down (vb cares of it, just shut down all clients so that the counter of references becomes 0).
In my case i used to copy the error object and pass it to a public error-event which could be handled in the exe.
'-------------------------
Public Event Error(ErrorInfo As vbpCloneErr.typGtwErrInfo)
Public Function ClosePopUp() As AmbientProperties
On Error GoTo hErr
'_________________________
.........
'_________________________
Exit Function
hErr:
Select Case Err
Case Else
If Not ExitForever Then
Call ErrCloner.Copy(ExtErrInfo,
Call SetExtErrInfo(TMPErrInfo, "vbpGtwCombo", "gtwCombo", "ClosePopUp", "Function", "{ControlName}")
Call SafeClosePopup
RaiseEvent Error(ExtErrInfo)
Select Case ExtErrInfo.ToDo
Case enmNoResponse
Call ShowError(ExtErrInfo)
Case enmResume
Resume
Case enmResumeNext
Resume Next
Case enmExitSub
Exit Function
Case enmEnd
ExitForever = True
Exit Function
End Select
End If
End Select
End Function
visualexp.,
Your code looks fine as you intend to handle the error by class2 nomatter where the error happens. Just make sure,
your error break option is set correct, and make sure the error is not handled in class1.
Your code looks fine as you intend to handle the error by class2 nomatter where the error happens. Just make sure,
your error break option is set correct, and make sure the error is not handled in class1.
(obviously, all points go to caraf_g!!!)