| | | | The first procedure is the Click event shown in Example 8-1, which caused the exception in the kernel32.dll library that exports the CopyMemory function. Thus, the reference to [<Non-Basic Code>] in Figure 8-2 refers to the external CopyMemory function. | | | | | | Example 8-1. A Click Event That Causes an Exception | | | | | | Private Sub cmdRaiseException_Click() Dim lpDest As Long Dim lng As Long On Error GoTo ERR_RaiseException lng = 5 CopyMemory ByVal lpDest, ByVal VarPtr(lng), 1 MsgBox Recovered from GPF Exit Sub ERR_RaiseException: MsgBox Err.Description Resume Next End Sub | | | | | | Now, in our replacement exception handler NewExceptionHandler, we do three things: | | | | | | We collect information about the exception in a string variable, say sError. | | | | | | We deliberately avoid enabling a VB error handler in NewExceptionHandler. In other words, we do not use On Error in this procedure. | | | | | | We deliberately place code in NewExceptionHandler to raise a VB error, using the sError value as the description of the error, as in: | | | | | | Err.Raise 1000, "NewExceptionHandler", sError | | | | | | Now, simply put, if an exception occurs, the call to Err.Raise will cause VB to look for a VB error handler. Since none exists in the offending NewExceptionHandler procedure, VB will search the call stack, skipping over the external code that caused the exception. Hence, in the case shown in Figure 8-2, the error handler in the cmdRaiseException_Click event will fire, thus displaying the description of the exception in a VB message box, as shown in Figure 8-3. | | | | | | We now have complete control over what happens next. For instance, in the error-handling code in cmdRaiseException_Click, we call Resume Next to continue execution, but of course there are other possibilities. The point is that the VB application will not terminate abruptly. | | |