Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

Real Time Exception Handling with Stack Trace

2.33/5 (5 votes)
2 Feb 2008Ms-PL3 min read 2   380  
Handle all the exceptions easily

Introduction

Exception handling is the major activity in application life cycle and especially for VB6 platform which doesn't provide much support for exception handling natively. This article might help to focus on the best way to debug the deployment version of your applications and to find out the exact problem on client machines.

This article aims to provide you the following:

  1. Systematic method of error handling
  2. System exceptions (Ex Access Violation) handling
  3. Automatic creation of log information and
  4. Crash reporter including stack trace (Yes! :-)

Background

How Debugger Works?

Windows provides an API named DebugActiveProcess to debug your applications. The debugger automatically receives the notifications from Windows for all exceptions of client process. Note that, debugging a process pauses all the threads of client application.

The client process can call OutputDebugString API to communicate with debugger. Normally application debugger handles the strings sent through OutputDebugString. If the application has no debugger, the system debugger handles the string. If the system debugger is also not active, string will be discarded.

Flow.jpg

Using the Code

How to Call Debugger?

StartDebug method of ClsErrorhandler class calls debugger by passing current process id as a parameter.

VB.NET
StartDebug(sDebuggerPath, sLogFilePath, sCrashStartApplication)

Using ErrorHandler Class

LogEvent Method

The application can call LogEvent method to pass the information to debugger. LogEvent method supports the following four functionalities:

S.No Type Usage
1 LogMessage Indicates as log message from application
2 vbError Indicates problem with application, but application can continue to execute
3 ApplicationError Indicates custom application error, but application can continue the operation
4 ApplicationCriticalError Indicates severe error and debugger will call crash application

Error Handling

Visual Basic provides On Error statement to handle the errors. Use this at the start of each procedure. TypeName functions return the name of class module and Form modules. For standard modules, you have to pass the name manually.

VB.NET
Private Sub CmdErrorHandle_Click()
On Error GoTo Errorhandler

Dim Dummy As Integer
'Raise Division by zero error
Dummy = 10 / Dummy

Exit Sub
Errorhandler: ObjErrorHandler.LogEvent TypeName(Me) & _
	"::CmdErrorHandle_Click", Err, ApplicationCriticalError
End Sub

LogEvent method automatically formats the error message from Error object received from the application.

VB.NET
lLastDllError = LError.LastDllError
'Call appropriate Module to get the error message from error number
If lLastDllError > 12000 Then
sDLLMessage = DebugErrorDescriptionWininet(lLastDllError)
If sDLLMessage <> "" Then lsAPIError = "WinInet Error _
		(" & lLastDllError & ") " & sDLLMessage
ElseIf lLastDllError > 0 Then
sDLLMessage = DebugErrorDescriptionWindows(lLastDllError)
If sDLLMessage <> "" Then lsAPIError = "Windows Error _
		(" & lLastDllError & ") " & sDLLMessage
End If

'Get VB error message
If LError.Number <> 0 Then
lsMessage = "Error (#" & Trim$(Str(LError.Number)) & "-" _
	& lLastDllError & ")-" & LError.Description & ", " & vbNewLine
End If
If lsAPIError <> "" Then lsMessage = lsMessage & lsAPIError & ", " & vbNewLine

'Get the module which generates error
If LError.Source <> "" Then sSource = " (generated by " & LError.Source & " Module)"

Convert Windows Error Number to Error Message

VB.NET
'Convert the Windows error number to meaningful error message.
Public Function DebugErrorDescriptionWindows_
	(Optional ByVal lErrNumber As Long = -1) As String
Dim strBuffer As String * 257
Dim dwLength As Long

If lErrNumber = -1 Then lErrNumber = GetLastError
dwLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS _
Or FORMAT_MESSAGE_MAX_WIDTH_MASK, ByVal 0&, lErrNumber, LANG_ENGLISH, _
ByVal strBuffer, 256&, 0&)
If dwLength > 0 Then DebugErrorDescriptionWindows = Left$(strBuffer, dwLength)
End Function

Converting DLL Error Number to Error Message

VB.NET
Public Function DebugErrorDescriptionWininet(lErrNumber As Long) As String
 Dim strBuffer As String * 257
 Dim dwLength As Long
 Dim hModule As Long
 Dim bLoadLib As Boolean
    
 'Get the handle if dll is already loaded by current process
 hModule = GetModuleHandle("wininet.dll")
 If hModule = 0 Then
  'if DLL is not loaded already, load it now
  hModule = LoadLibrary("wininet.dll")
  bLoadLib = True
 End If
 dwLength = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, _
	ByVal hModule, lErrNumber, 0&, ByVal strBuffer, 256&, 0&)
 If dwLength > 0 Then DebugErrorDescriptionWininet = Left$(strBuffer, dwLength - 2)
 If bLoadLib Then FreeLibrary hModule
 'if DLL is loaded for this function then unload it
End Function

Raising Custom Errors

To raise custom application errors, call LogEvent method with your error description and pass ApplicationError as log type.

VB.NET
ObjErrorHandler.LogEvent "Pass your custom error message here", , ApplicationError 

Store Application Log

To raise custom application messages, call LogEvent method with your message and pass LogMessage as log type.

VB.NET
ObjErrorHandler.LogEvent "Sample Log Current Time : " & Now, , LogMessage 

Crash Report

If debugger found crash in application, it will automatically execute the crash reporter provided by the application.

crash.jpg

Error Handling in IDE

If you want to debug your code during the development phase, you can enable the ShowMessageBox property.

VB.NET
ObjErrorHandler.ShowMessageBox = True
Error.jpg

Stack Trace & Symbol File

The VB6 compiler provides the option to create symbol file (with extension PDB) through Create Symbol Debug info option of project properties window. By using this symbol file debugger maps the function address to names.

Project_properties_symbol.jpg

By default, address of functions are logged by debugger instead of function names on client machine to avoid security problems. After receiving report from the client, you can use Stack Converter tool to convert addresses to function names.

stack.jpg

But if you prefer, you can deploy symbol file (.pdb) on your client machine and can call DebugSendTrace method to log full stack trace with function name.

Points of Interest

There are no additional requirements to release this executable with your existing application. You can use this tool with Power basic and VC++ applications also. But this debugger has been designed and tested mainly for VB6 applications.

History

  • Release version 1.0 on 02/02/2008

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)