XCrashReport
XCrashReport provides an easy way to add exception handling and crash reporting
to your application. XCrashReport captures information when the exception occurs,
and your user is then offered the choice to send you the information via email.
The exception handler uses no STL, WTL, MFC, or boost.
The ancillary stand-alone programs do, however, use MFC.
I want to thank Bruce Dawson, Mike Carruth, and Grant McDorman, on whose work I was able to build XCrashReport.
Changes in XCrashReport v2.0
| All code and projects converted to VS2005 and VS2008 | |
| Crash handler now fully supports Unicode | |
| XCrashHandler supports 64-bits. Major parts of the exception handler were rewritten to accommodate 64-bit registers, and all the inline asm code was replaced with compiler intrinsics, since Visual Studio does not allow inline asm code in x64 builds. The XCrashHandlerTest demo has both x86 and x64 builds. | |
| You now can optionally choose to send screenshots of each monitor on your user's system. The user is shown these screenshot files in the XCrashReport application, and can choose whether to send them or not. Included is XBmpViewer, which will display the screenshot when the user double-clicks a screenshot file name. | |
All files generated by XCrashHandler are now put in the user's documents
folder (CSIDL_PERSONAL) to avoid UAC interaction.
|
|
The email send-to address and name are now read from
XCrashReport.ini, which is
loaded from the user's documents folder (CSIDL_PERSONAL),
again because of UAC.
|
|
| Another crash test was added to the demo app, to generate a crash from a worker thread. | |
It is no longer necessary to include ExceptionAttacher.cpp.
XCrashHandler now automatically calls
SetUnhandledExceptionFilter()
to install its exception handler. This is done by using
init_seg(lib),
so that XCrashHandler is initialized before your app starts.
|
|
| File paths in the [FilesToAdd] section of XCrashReport.ini may now incorporate environment variables. | |
| The computer and domain names are now included in ERRORLOG.TXT. | |
| A dump of the environment variables is now included in ERRORLOG.TXT. | |
| Added code to prevent the CRT from forcing a call to WER (Windows Error Reporting) | |
| Added support for SMTP with SSL (SSL is required by gmail and other web-based email). This means that users do not need to have an email client program installed, in order to send error report. | |
| New XSmtpConfig.exe utility allows easy configuration of SMTP settings: |
KNOWNFOLDERID values. If you follow this advice, your code
will not work on pre-Vista systems. The code for this article uses only
CSIDL_PERSONAL when reading or writing files.
Demo App: XCrashReportTest.exe
Here is the demo app:
EXCEPTION_CONTINUE_SEARCH.
This tells Win32 that this handler didn't actually handle the exception, so that
things will proceed as per normal, and the debugger will catch the exception.
If not running under a debugger, the handler attempts to run XCrashReport.exe.
If this is successful, the handler returns EXCEPTION_EXECUTE_HANDLER,
which suppresses the standard crash dialog. If not successful, the handler returns
EXCEPTION_CONTINUE_SEARCH, which again lets things proceed as per normal
(the standard crash dialog will pop up).
XCrashReportTest.exe includes the XCrashHandler exception handler, which catches the exception, gathers system information, and writes ERRORLOG.TXT, the minidump file CRASH.DMP, and the screenshot image files (one for each monitor).
You can use What's This? help to see what code will be executed when a button is pressed:
Next Stop: XCrashReport.exe
As with the previous version, I try to do as little as possible in the exception handler, which is running in the process space of the crashed app. When the handler completes, it attempts to run XCrashReport.exe. Of course, the assumption is that XCrashReport.exe is in the same folder as the exe of the crashed app.
When XCrashReport.exe starts, it immediately exports any registry keys you have specified, and then shows this dialog:
At this point your user will be offered the opportunity to inspect the files that will be zipped and sent via email:
Double-clicking any file in the list will display the file in the view window. Text files will be shown as text, and binary files will be shown in hex. Screenshot bmp files will be displayed in the standalone XBmpViewer app.
Notice the two .bmp screenshot files. Although they are 4.5 MB each, they will be compressed by over 90% when zipped.
You may want to send other files that are associated with your app. In the above screenshot, you can see files mobydick_ansi.txt, etc. These files and other settings are specified in XCrashReport.ini.
Your user can now choose whether to send the files he has approved, or just cancel.
Back at the Ranch
You are relaxing with the latest XKCD when something hits your inbox. A crash dump for the company's new product! What to do?!?!Fortunately you don't need to use WinDbg anymore. Extract CRASH.DMP from the zip file to the folder where you saved the app's .pdb file (you did save it, didn't you?), double-click the CRASH.DMP file and VS2008 starts up. Click Start Debugging (F5) and you will see the unhandled exception message box:
Click the Break button, and you will be taken to the source line that caused the exception:
How Does It Work?
This all works because VS2008 uses the app's .pdb file. To generate a .pdb file for release builds, go to
Project | Properties | C/C++ | Debug Information Formatand select Program Database (/Zi):
Every time you create a new release build, you should archive both the .pdb and .exe files.
XCrashReport Architecture
I have stepped through what happens when your app crashes and the XCrashHandler exception handler is invoked, and what the XCrashReport GUI app looks like. This diagram shows how all the pieces fit together:
"Other files" include any additional files you have specified in XCrashReport.ini.
Verified Platforms
XCrashReport has been verified to work correctly (with no UAC interaction) on the following platforms:
| OS | Version | Service Pack | Notes |
|---|---|---|---|
| 2000 | Professional | SP4 | Requires dbghelp.dll |
| XP 32-bit | Professional | SP2 | |
| Vista 32-bit | Ultimate | Standard (restricted) user | |
| Windows 7 32-bit | Professional | Standard (restricted) user | |
| Windows 7 64-bit | Professional | Standard (restricted) user |
Windows 2000 was the only OS that was missing dbghelp.dll; on all other systems, XCrashReport worked fine using the dbghelp.dll already on the system.
If you have verified that XCrashReport works on other platforms/service packs, please send me email so I can add to list.
How To Use
Step 1: Include XCrashHandler Files in your project
All the files you need to include are in the XCrashHandler folder in the download:- CrashOptions.h
- MiniVersion.cpp
- MiniVersion.h
- Screenshot.cpp
- Screenshot.h
- XCrashHandler.cpp
- XCrashHandler.h
- XGetWinVer.cpp
- XGetWinVer.h
Aside from editing two files (see below), that's all you have to do.
There is no more "ExceptionAttacher" as in the previous version. Setting up the
exception handler is now done automatically via static object
g_XCrashHandler in XCrashHandler.cpp. The
init_seg(lib)
initializes this static as if it
was a library, which means it's set up before your app is initialized.
You can simply include XCrashHandler files in any project, customize
XCrashReport.ini and CrashOptions.h, and you're good to go.
Step 2: Edit XCrashReport.ini
Edit XCrashReport.ini to customize registry, files, and email settings. Note that trying to access a registry key outside of HKCU may involve interaction with UAC.; ; sample XCrashReport.ini file v2.0.1 ; [RegistryToAdd] ;RegistryNNN=registry path,description Registry001=HKCU\Software\CodeProject\XCrashReportTestRU86,Main reg key Registry002=HKCU\Software\CodeProject\XCrashReportTestRU86\Program,another reg key [FilesToAdd] ;FileNNN=file path,description,type,text flag File001=mobydick_ansi.txt,moby dick ansi,Text Document,1 File002=d:\temp\mobydick_unicode_with_bom.txt,moby dick unicode+bom,Text Document,1 File003=d:\temp\mobydick_unicode_no_bom.txt,moby dick unicode,Text Document,1 File004=%TEMP%\mydata.txt,my important data,Text Document,1 [Email] ; 0 = use MAPI (must have email client installed) ; 1 = use SMTP (for web email service like gmail) SendEmail=0 ;============================================================================== ; next two entries are for email destination SendToName=BozoSoft Software Support SendToAddress=support@bozosoft.com ;============================================================================== ; next entries are for SMTP email (gmail, yahoo, hotmail, msn, etc.) SmtpName= SmtpUserName= SmtpEmailAddress= SmtpPassword= ;============================================================================== SmtpServer=smtp.gmail.com ;SmtpServer=smtp.live.com ;SmtpServer=smtp.email.msn.com ;SmtpServer=smtp.mail.yahoo.com or plus.smtp.mail.yahoo.com ;============================================================================== ; customary smtp ports: 25 465 587 SmtpPort=465 ;============================================================================== ; Plain Text = 0 ; SSL / TLS = 1 ; STARTTLS = 2 SmtpConnType=1 ;============================================================================== ; None = 0 ; CRAM MD5 = 1 ; AUTH LOGIN = 2 ; AUTH PLAIN = 3 ; NTLM = 4 ; Auto Detect = 5 SmtpAuthType=3 SmtpEncoding=iso-8859-1As the FILE004 entry shows, you can use environment variables in the [FilesToAdd] section. You must ensure that the resulting path is properly formed - i.e., that the backslash '\' character is added if necessary.
XCrashReport.ini is not written to by XCrashHandler or XCrashReport.
XSmtpConfig.exe may be used by you or your end users to configure SMTP settings:
Step 3: Edit XCrashOptions.h
Edit XCrashOptions.h to customize program options and file names. To avoid accidental duplication of names by other programs, you can customize the file names to something specific to your product and company. This includes the name of XCrashReport.ini.
///////////////////////////////////////////////////////////////////////////////
// SCREENSHOT
///////////////////////////////////////////////////////////////////////////////
// comment out this line if you don't want screenshots
#define XCRASHREPORT_WRITE_SCREENSHOT
// Up to 16 screenshots will be generated, one for each monitor on the user's
// system. You can reduce this to any number below 16.
#define XCRASHREPORT_SCREENSHOT_MAX_MONITORS 16
#define XCRASHREPORT_SCREENSHOT_RESOLUTION_LOW 1
#define XCRASHREPORT_SCREENSHOT_RESOLUTION_MEDIUM 2
#define XCRASHREPORT_SCREENSHOT_RESOLUTION_HIGH 3
// This controls how big the screenshot files are. The files are BMP files,
// and so will be compressed substantially when zipped.
#define XCRASHREPORT_SCREENSHOT_RESOLUTION XCRASHREPORT_SCREENSHOT_RESOLUTION_HIGH
///////////////////////////////////////////////////////////////////////////////
// MINIDUMP
///////////////////////////////////////////////////////////////////////////////
// comment out this line if you don't want minidumps
#define XCRASHREPORT_WRITE_MINIDUMP
///////////////////////////////////////////////////////////////////////////////
// FILE NAMES
///////////////////////////////////////////////////////////////////////////////
#define XCRASHREPORT_MINI_DUMP_FILE _T("CRASH.DMP")
#define XCRASHREPORT_ERROR_LOG_FILE _T("ERRORLOG.TXT")
#define XCRASHREPORT_REGISTRY_DUMP_FILE _T("REGISTRY.TXT")
#define XCRASHREPORT_BMP_FILE _T("XCRASHREPORT_Mon")
#ifdef _UNICODE
#define XCRASHREPORT_CRASH_REPORT_APP _T("XCrashReportRU.exe")
#define XCRASHREPORT_BMPVIEWER_APP _T("XBmpViewerRU.exe")
#else
#define XCRASHREPORT_CRASH_REPORT_APP _T("XCrashReportRA.exe")
#define XCRASHREPORT_BMPVIEWER_APP _T("XBmpViewerRA.exe")
#endif
///////////////////////////////////////////////////////////////////////////////
// INI FILE
///////////////////////////////////////////////////////////////////////////////
#define INI_FILE_NAME _T("XCrashReport.ini")
#define INI_EMAIL_SECTION _T("Email")
#define INI_EMAIL_SEND_METHOD _T("SendMethod")
#define INI_EMAIL_SEND_TO_NAME _T("SendToName")
#define INI_EMAIL_SEND_TO_ADDRESS _T("SendToAddress")
#define INI_FILE_SECTION _T("FilesToAdd")
#define INI_FILE_TEMPLATE _T("File%03d")
#define INI_REG_SECTION _T("RegistryToAdd")
#define INI_REG_TEMPLATE _T("Registry%03d")
#define MAX_INI_ITEMS 999
#define INI_SMTP_NAME _T("SmtpName")
#define INI_SMTP_EMAIL_ADDRESS _T("SmtpEmailAddress")
#define INI_SMTP_USER_NAME _T("SmtpUserName")
#define INI_SMTP_PASSWORD _T("SmtpPassword")
#define INI_SMTP_SERVER _T("SmtpServer")
#define INI_SMTP_PORT _T("SmtpPort")
#define INI_SMTP_CONN_TYPE _T("SmtpConnType")
#define INI_SMTP_AUTH_TYPE _T("SmtpAuthType")
#define INI_SMTP_ENCODING _T("SmtpEncoding")
///////////////////////////////////////////////////////////////////////////////
// SMTP - password decryption key
//
// The following GUID is used to decrypt the email address and password in
// SMTP authentication. It is strongly suggested that you replace this GUID
// with one that you create yourself, to avoid any possible security breach.
// This key is used by XSmtpConfig.exe and CrashReport.exe.
///////////////////////////////////////////////////////////////////////////////
#define SMTP_PASSWORD_KEY _T("35DCE3D2-23A1-41b9-A429-BFA03C3C3765")
///////////////////////////////////////////////////////////////////////////////
// EMAIL - name and address are specified in INI file
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// REGISTRY - keys are specified in INI file
///////////////////////////////////////////////////////////////////////////////
// comment out this line if you don't want to export registry keys
#define XCRASHREPORT_DUMP_REGISTRY
Step 4: Compile and Prepare Installation Package
After compiling your app to include the XCrashHandler files, you need to include the following files in the installation package:- XCrashReport.ini - configuration settings for XCrashReport. Make sure its name matches whatever is in CrashOptions.h. Install to CSIDL_PERSONAL.
- XSmtpConfig.exe - GUI utility that lets your end users configure SMTP settings. This is not necessary if your users will always use an email client.
- XCrashReport.exe - include the desired version of the GUI report app. Make sure its name matches whatever is in CrashOptions.h. Install to your app's exe folder.
- XBmpViewer.exe - necessary if you want to allow your users to view the screenshots. Make sure its name matches whatever is in CrashOptions.h. Install to your app's exe folder.
-
dbghelp.dll - This might already be on your users' systems;
according to MSDN, XP and later systems ship with dbghelp.dll.
If you want to include it, there is a dbghelp folder in the
download that contains x86 and x64 versions of dbghelp.dll
from the latest
Windows SDK download.
Install to your app's exe folder.
DO NOT INSTALL DBGHELP.DLL TO A SYSTEM FOLDER!
Known Limitations
- XCrashReport.exe must reside in the same folder as the application's exe.
- XCrashReport.ini must be placed in CSIDL_PERSONAL.
- Applications that are packed with UPX or protection systems like Armadillo will generate a CRASH.DMP file, but this file cannot be loaded into VS2008 to show source location.
- Stack overflows are not caught by XCrashHandler.
-
For standard (restricted) users, trying to export registry keys that are in
HKLM, or trying to access files that are not in a user folder, may result in interaction with UAC. -
If you get the error "invalid email address",
try adding "SMTP:" to the send-to address in XCrashReport.ini:
SendToAddress=SMTP:support@bozosoft.com
Links
Revision History
Version 2.0.1 - 2010 July 26
- Licensed under Hans Dietrich Software Terms of Use.
- Added code to prevent the CRT from forcing a call to WER (Windows Error Reporting)
- Added support for SMTP with SSL (SSL is required by gmail and other web-based email). This means that users do not need to have an email client program installed.
- New XSmtpConfig.exe utility allows easy configuration of SMTP settings.
Version 1.4.1 - 2010 July 2
- Fixed problem with file path display in XCrashReportTest.
Version 1.4 - 2010 June 30
- All code and projects converted to VS2008
- All projects now have ANSI and Unicode builds
- Now supports 64-bits
- Optional screenshots
- All files now put in the user's documents folder
(
CSIDL_PERSONAL) to avoid UAC interaction - XCrashReport.ini now read from user's documents folder
(
CSIDL_PERSONAL) to avoid UAC interaction - The email send-to address and name are now read from XCrashReport.ini
- Crash test was added to the demo app to generate a crash from a worker thread
- It is no longer necessary to include ExceptionAttacher.cpp.
XCrashHandler now automatically calls
SetUnhandledExceptionFilter()to install its exception handler - File paths in the [FilesToAdd] section of XCrashReport.ini may now incorporate environment variables
- The computer and domain names are now included in ERRORLOG.TXT
- A dump of environment variables is now included in ERRORLOG.TXT
Version 1.1 - 2003 October 19
- Initial public release
Buy latest version
| Buy XCrashReport 2.0 license – $80.00 per developer. Includes full C++ source code to XCrashHandler (to include in your app), XCrashReport, XCrashReportTest (demo to generate crash), XBmpViewer, and XSmtpConfig utility. |