|
What's new in this version?
- .NET support - now BugTrap supports native, managed and mixed assemblies.
- Source code - I have been criticized for missing source code many times. Full source code of BugTrap is included!
- Thread isolation - BugTrap suspends all threads in the application and displays GUI from a separate thread. This approach improves stability and prevents new errors that could be thrown by other threads.
Introduction
Some time ago, I was working on a multi-tier application with quite complex logic. The application was handling medical information, and it was important to correctly synchronize data under all circumstances. I put extra code to make the application as stable as possible, and added automatic backups and self-recovery. Do you think it solved all problems?
No, I was still searching for a tool to handle problems, seen by customers, remotely. How could I assist them and debug the problem if I lived on the other side of the globe? Eventually, I found this excellent Jim Crafton article about a tool capable of intercepting unhandled errors. That was a solution!
Unfortunately, the original black-box was not customizable, it didn't support mini-dump files or Unicode strings, and it didn't have any server. In spite of these limitations, it was an excellent starting point because I knew exactly what kind of a tool I wanted. I started working on my own tool in hope to make it flexible and customizable, and a powerful solution.
Overview
Usually, it's very frustrating to receive a message from your customer saying that your program doesn't work. Most users may not let you know what's incorrect in your application and which piece of code went wrong. Windows has a built-in handler for unhandled errors, however, this default handler might be useless when errors happen on the customer side, because you rarely want to send your error report to Microsoft:

BugTrap solves this problem by overriding the default error handler. BugTrap gathers error details such as address, call stack, and the computer environment. It's also possible to add an arbitrary number of custom log files, with additional information on the default error report, using built-in or external logging functions.
BugTrap may save error reports on the disk, or automatically deliver error reports to the developer's computer by e-mail, over HTTP, or through a fast low-level TCP-based network protocol. The BugTrap server automatically manages the error reports repository, and notifies developers about any new errors.

BugTrap stores error descriptions in log and mini-dump files. Mini-dump files may be opened in Microsoft Visual Studio .NET and in WinDbg. The BugTrap package also includes a CrashExplorer utility that can extract symbolic information from MAP and PDB files. There is a special BugTrap version for .NET applications (currently under development).



All details are available in the BugTrap documentation. The documentation is also included as part of the Setup. If you like to know how BugTrap works, you may read these articles:
Adding BugTrap support to Win32 applications
BugTrap is redistributed as a dynamic-link library (DLL). Two versions of the BugTrap DLL are available: the ANSI version, and the Unicode version.
and the Unicode version.
| DLL name |
Character encoding |
| BugTrap.dll |
ANSI multi-byte character strings |
| BugTrapU.dll |
Unicode strings |
The code bellow adds BugTrap support to Win32 applications: #include "BugTrap.h"
#pragma comment(lib, "BugTrap.lib")
static void SetupExceptionHandler()
{
BT_SetAppName(_T("Your application name"));
BT_SetSupportEMail(_T("your@email.com"));
BT_SetFlags(BTF_DETAILEDMODE | BTF_EDIETMAIL);
BT_SetSupportServer(_T("localhost"), 9999);
BT_SetSupportURL(_T("http://www.your-web-site.com"));
}
The SetupExceptionHandler() function may be called from InitInstance() or main(), depending on the type of your application.
When your application experiences a problem, the user is prompted by BugTrap to submit an error report to the BugTrap server. The error report includes many details of the user environment. The report also includes a complete stack trace for the call that caused a problem.
With BugTrap, you can debug the problem using two different approaches.
1. You can open post-mortem mini-dump files in Visual Studio:

2. You can use the built-in utility CrashExplorer:
When BugTrap is building stack traces, it searches for the PDB file – a file that holds debugging information. If this file is available, BugTrap is able to show function names and line numbers next to each address. Obviously, the PDB file makes the stack trace much nicer, but most developers prefer not to distribute PDB files to end users because PDB files could simplify program reverse engineering.
Therefore, BugTrap doesn't require PDB files on user computers. Instead, it saves raw function addresses to the log:

So, the end user doesn't have any clue what's behind of these hexadecimal numbers.
CrashExplorer reverts back all functions names and line numbers based on the PDB/MAP file and addresses in a log:

Adding BugTrap support to .NET applications
The .NET version of BugTrap is redistributed as managed library: BugTrapN.dll. This DLL consists of managed and unmanaged code. Such design lets BugTrap support pure managed .NET assemblies as well as mixed C++ assemblies that could throw managed .NET exceptions and native Win32 exceptions.
BugTrap for .NET exposes both managed and unmanaged (native) interfaces. Managed interface is accessible from C# or VB.NET code:
ExceptionHandler.AppName = "Your application name";
ExceptionHandler.Flags = FlagsType.DetailedMode | FlagsType.EditMail;
ExceptionHandler.DumpType = MinidumpType.NoDump;
ExceptionHandler.SupportEMail = "your@email.com";
ExceptionHandler.SupportURL = "http://www.your-web-site.com";
ExceptionHandler.SupportHost = "localhost";
ExceptionHandler.SupportPort = 9999;
Unmanaged interface is accessible from native Win32 code and was discussed earlier. It is possible to use any interface or even both interfaces in the same application.
Updates
I periodically fix errors and add new features. This frequency of such updates depends on your feedback. You may check my web site for the most recent updates. All major updates are submitted to http://www.codeproject.com/
Building notes
Most developers may go ahead and download the Setup - it installs all necessary files and components. However, some professionals enjoy building all components from scratch. Those developers may download BugTrap source code.
I have been trying to make BugTrap DLL as compact as possible. Therefore BugTrap DLL does not use MFC/ATL/WTL. I have been using pure C and C++. In particular, you will find several classes from my own library: collection classes, IO streams, built-in XML parser, etc. BugTrap DLL depends on zlib. I have included it in the archive to simplify building.
CrashExplorer depends on STL, Boost and WTL. Both libraries must be pre-installed on your computer.
That's it! Happy bug-trapping!
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 363 (Total in Forum: 363) (Refresh) | FirstPrevNext |
|
 |
|
|
 |
|
|
It is supposed to work on Win2K. Let me install Win2k and play with it. If it doesn't work, I will release an update.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thanx for your quick response...
i got the following MessageBox (i'll try to translate^^): "BugTrapTestD.exe has an error occured. Please restart the program. An Errorprotocol will build." -> bad english, i know ^^
I work with Win2000 SP3 in VMWare on a QuadCore... The VM use 1 Processor and 1 GB RAM...
Thanks a lot...
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I reproduced the issue: BugTrap was crashing because you didn't put the recent version of dbghelp.dll next to BugTrap.dll. The version that comes with Windows 2000 doesn't support the minimal set of functions required by BugTrap.
The problem could be solved by copying the recent version of dbghelp.dll from Vista/XP System32 folder to the folder with BugTrap.dll.
Also, I am going make sure that the next version of BugTrap.dll won't crash in such conditions. It won't crash, but won't work either. The user will see pretty much empty error report with no information. I do not want to add some extra stuff like messages saying that dbghelp.dll is incompatible because this case is not normal. According to BugTrap manual, you were supposed to distribute BugTrap.dll along with dbghelp.dll.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thanx again. u save me lot of time...
i distribute the dbghelp.dll...
for Server2003-OS u must distribute shlwapi.dll...
Greets ^^
modified on Monday, January 5, 2009 7:23 AM
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
"GetSaveFileName" in function "SaveReport" in File "MainDlg.cpp" hangs infinite...
What can i do?
i work with VS2005 SP 1 and Vista x64...
the error occurs only if add manual Files with function BT_AddLogFile in Error-Handler-Callback registered by BT_SetPreErrHandler... i can't find the reason... *mpf*
if i add no files, the zip-savedlg is shown...
Thanks for Relpys...
EDIT: very mysterious, if i add messageboxes for debugging, e.g. in GetCanonicalAppName the savedlg is shown - without messageboxes the savedlg isn't shown and the app hangs... all in Debug-Mode... *mpf*
EDIT: under XP savedlg is shown, but the zip-file was only saved if i don't add Files per callback, else it hangs...
modified on Monday, December 29, 2008 11:40 AM
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
define an HookProc in OPENFILENAME-struct for GetSaveFileName-function
then the style of dlg is old not nice, but working
Problem is the Explorer-Style... don't set OFN_EPLORER-Flag!!!!! (it hangs up -> infinite)
modified on Monday, December 29, 2008 3:25 PM
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
there must be something else. I modified BugTrapTest as follows and it is perfectly working on Vista-x64 SP1 as well as on Win XP SP3:
static void CALLBACK ErrHandler(INT_PTR /*nErrHandlerParam*/) { BT_AddLogFile(_T("C:\\ReadMe.txt")); }
CBugTrapTestApp::CBugTrapTestApp() { ... BT_SetPreErrHandler(ErrHandler, 0); }
If you have an example that is not working, please email it to "makspyat at gmail dot com".
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Our company uses a dual monitor setup for our software product, so I added support for up to four monitors in your screendump facility. I thought you might be interested in the code.
I marked the changed lines with "// !!!" - I hope I got them all. These are the changes I made (sorry about the indenting, it didn't seem to paste correctly):
CSymEngine::CScreenShot::CScreenShot(void) { BOOL bResult = FALSE; ZeroMemory(this, sizeof(*this)); for (int iDevNum = 0; iDevNum < 4; iDevNum++) // !!! start modification { DISPLAY_DEVICE displayDevice; displayDevice.cb = sizeof(DISPLAY_DEVICE); if (!EnumDisplayDevices(0, iDevNum, &displayDevice, 0)) break; HDC hDisplayDC = CreateDC(displayDevice.DeviceName, NULL, NULL, NULL); // !!! end modification if (hDisplayDC) { int nWidth = GetDeviceCaps(hDisplayDC, HORZRES); int nHeight = GetDeviceCaps(hDisplayDC, VERTRES); HBITMAP hBitmap = CreateCompatibleBitmap(hDisplayDC, nWidth, nHeight); if (hBitmap) { HDC hMemDC = CreateCompatibleDC(hDisplayDC); if (hMemDC) { HBITMAP hbmpSafeBitmap = SelectBitmap(hMemDC, hBitmap); BitBlt(hMemDC, 0, 0, nWidth, nHeight, hDisplayDC, 0, 0, SRCCOPY);
BITMAP bmpInfo; GetObject(hBitmap, sizeof(bmpInfo), &bmpInfo); WORD wPalSize, wBmpBits = bmpInfo.bmPlanes * bmpInfo.bmBitsPixel; if (wBmpBits <= 1) { wBmpBits = 1; // monochrome image wPalSize = 2; } else if (wBmpBits <= 4) { wBmpBits = 4; // palette-based 4 bpp image wPalSize = 16; } else if (wBmpBits <= 8) { wBmpBits = 8; // palette-based 8 bpp image wPalSize = 256; } else { wBmpBits = 16; // force to 16 bpp image (don't allow 24 bpp) wPalSize = 0; // don't use palette }
m_dwBmpHdrSize[iDevNum] = sizeof(BITMAPINFOHEADER) + wPalSize * sizeof(RGBQUAD); // !!! start modification m_pBmpInfo[iDevNum] = (PBITMAPINFO)new BYTE[m_dwBmpHdrSize[iDevNum]]; if (m_pBmpInfo[iDevNum]) { ZeroMemory(m_pBmpInfo[iDevNum], m_dwBmpHdrSize[iDevNum]); BITMAPINFOHEADER& bmpHdr = m_pBmpInfo[iDevNum]->bmiHeader; // !!! end modification bmpHdr.biSize = sizeof(bmpHdr); bmpHdr.biWidth = nWidth; bmpHdr.biHeight = nHeight; bmpHdr.biPlanes = 1; bmpHdr.biBitCount = wBmpBits; bmpHdr.biCompression = BI_RGB;
// call GetDIBits with a NULL bits array, so it will calculate the biSizeImage field GetDIBits(hMemDC, hBitmap, 0, nHeight, NULL, m_pBmpInfo[iDevNum], DIB_RGB_COLORS); // !!! modified if (bmpHdr.biSizeImage == 0) bmpHdr.biSizeImage = (wBmpBits * nWidth + 31) / 32 * 4 * nHeight; m_dwBitsArraySize[iDevNum] = bmpHdr.biSizeImage; // !!! modified m_pBitsArray[iDevNum] = new BYTE[m_dwBitsArraySize[iDevNum]]; // !!! modified if (m_pBitsArray) { if (GetDIBits(hMemDC, hBitmap, 0, nHeight, m_pBitsArray[iDevNum], m_pBmpInfo[iDevNum], DIB_RGB_COLORS)) // !!! modified bResult = TRUE; } }
SelectBitmap(hMemDC, hbmpSafeBitmap); DeleteDC(hMemDC); } DeleteBitmap(hBitmap); } DeleteDC(hDisplayDC); } if (! bResult) { delete[] (PBYTE)m_pBitsArray; delete[] (PBYTE)m_pBmpInfo; ZeroMemory(this, sizeof(*this)); break; // !!! modified } } // !!! modified }
BOOL CSymEngine::CScreenShot::WriteScreenShot(PCTSTR pszFileName) { if (! m_pBmpInfo[0]) // !!! modified return FALSE; TCHAR screenShotFile[MAX_PATH]; // !!! start modification TCHAR iDevNumStr[8]; for (int iDevNum = 0; m_pBmpInfo[iDevNum] && (iDevNum < 4); iDevNum++) { _tcscpy_s(screenShotFile, MAX_PATH, pszFileName); _itot_s(iDevNum, iDevNumStr, sizeof(iDevNumStr), 10); _tcscat_s(screenShotFile, MAX_PATH, iDevNumStr); _tcscat_s(screenShotFile, MAX_PATH, _T(".BMP")); HANDLE hFile = CreateFile(screenShotFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); // !!! end modification if (hFile != INVALID_HANDLE_VALUE) { BITMAPFILEHEADER bmpfh; ZeroMemory(&bmpfh, sizeof(bmpfh)); bmpfh.bfType = 'MB'; bmpfh.bfOffBits = sizeof(bmpfh) + m_dwBmpHdrSize[iDevNum]; // !!! modified bmpfh.bfSize = bmpfh.bfOffBits + m_dwBitsArraySize[iDevNum]; // !!! modified DWORD dwProcessedNumber; WriteFile(hFile, &bmpfh, sizeof(bmpfh), &dwProcessedNumber, NULL); WriteFile(hFile, m_pBmpInfo[iDevNum], m_dwBmpHdrSize[iDevNum], &dwProcessedNumber, NULL); // !!! modified WriteFile(hFile, m_pBitsArray[iDevNum], m_dwBitsArraySize[iDevNum], &dwProcessedNumber, NULL); // !!! modified CloseHandle(hFile); //return TRUE; // !!! modified } else return FALSE; } // !!! modified return TRUE; // !!! modified }
BOOL CSymEngine::WriteReportFiles(PCTSTR pszFolderName, CEnumProcess* pEnumProcess) { PCTSTR pszLogExtension = GetLogFileExtension(); if (pszLogExtension == NULL) return FALSE; TCHAR szLogFileName[MAX_PATH]; _stprintf_s(szLogFileName, countof(szLogFileName), _T("errorlog.%s"), pszLogExtension); TCHAR szFullLogFileName[MAX_PATH]; PathCombine(szFullLogFileName, pszFolderName, szLogFileName); if (! WriteLog(szFullLogFileName, pEnumProcess)) return FALSE;
if (g_eDumpType != MiniDumpNoDump) { TCHAR szFullDumpFileName[MAX_PATH]; PathCombine(szFullDumpFileName, pszFolderName, _T("crashdump.dmp")); if (FMiniDumpWriteDump != NULL && ! WriteDump(szFullDumpFileName)) return FALSE; }
if (m_pScreenShot) { TCHAR szFullScreenShotFileName[MAX_PATH]; PathCombine(szFullScreenShotFileName, pszFolderName, _T("screenshot")); // !!! modified if (! m_pScreenShot->WriteScreenShot(szFullScreenShotFileName)) return FALSE; }
return TRUE; }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thanks for your post! Your code will be integrated into the next version of BugTrap, which is about to be release pretty soon.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I am trying to compile the new version with VS2005. The .NET Release and .NET Debug projects do not build. I get the following error:
z:\dev\code\sdk\bugtrap\win32\bugtrap\NetThunks.h(163) : error C3821: 'System::Exception ^': managed type or function cannot be used in an unmanaged function .\SymEngine.cpp(2057) : see reference to function template instantiation 'bool NetThunks::IsNull<System::Exception>(gcroot<T> ' being compiled with [ T=System::Exception ^ ] z:\dev\code\sdk\bugtrap\win32\bugtrap\NetThunks.h(163) : error C3642: 'gcroot<T>::operator T(void) const' : cannot call a function with __clrcall calling convention from native code with [ T=System::Exception ^ ] z:\dev\code\sdk\bugtrap\win32\bugtrap\NetThunks.h(164) : error C3821: 'object': managed type or function cannot be used in an unmanaged function
Not sure whether this is due to your targeting the .NET 3.5 Framework, but I wouldn't expect it to be...
Any ideas?
- Lutz
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Lutz, unfortunately I am not using VS 2005 and it looks like our code is not synchronized anymore... If you still need an answer, please print the full line text (and not the number that is not working for you).
BugTrap is built against .NET Framework 2.0, and I suspect that you are getting this error because of difference between C++ compiler in VS2005 & VS2008.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Just in case anyone wasn't aware, Maksim has updated with a new version 1.2.3248.41806 on 23 Nov 2008 with snapshot support.
Mike
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hi Maksim
Thanks - a neat bit of code. I tried building the bugTrap DLL on its own using VS2003. Not surprisingly there were errors, mainly to do with the safe versions of strcpy, etc, etc. That's no problem - where I am confused is with the reference to zip.h in the stdafx.h file. Which zip file library did you use? I cannot see a component with that name in the code I downloaded from this page. Any clues?
Kind Regards
Jerry
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hello Maksim
Thanks - that explains the confusion. I've got zlib sources here and the main header file is zlib.h
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I'm writing a plug-in DLL in C that runs inside a third-party application. If my DLL generates a recoverable exception, I catch the exception with SEH, set a global flag instructing my DLL not to do anything else (since it's internal state may be corrupt), but allow the third-party application to continue to run. I'd like to use BugTrap to interpret the _EXCEPTION_POINTERS structure that I get from __except and create some kind of log or dump that can be sent to me to debug my DLL using my private PDBs.
Can BugTrap do that? It looks kind of like BT_SehFilter() might do what I want, but the not in the .h file says "Don't call this function".
Thanks in any case. It looks to be a pretty impressive library!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
BT_SehFilter() will not do exactly what you need: it will display BugTrap GUI and terminate the application. You need something like a BT_SaveSnapshot/BT_MailSnapshot/BT_SendSnapshot where you would pass a pointer returned by GetExceptionInformation().
Right now none of these functions take PEXCEPTION_POINTERS, but I could add missing functionality on this weekend.
Would it be Ok with you?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
It appears that whenever I open a new log file at the begining of my application all new log entries get appended to the existing contents of the log file. What I would like to do is to flush the contents of the file before new entries are added. I call BT_FlushLogFile, but it does not seem to do anything.
Here is a code segment
INT_PTR BT_LogHandle = BT_OpenLogFile(NULL, BTLF_TEXT);
BT_FlushLogFile (BT_LogHandle); BT_SetLogSizeInEntries (BT_LogHandle, 200);
BT_SetLogFlags (BT_LogHandle, BTLF_SHOWLOGLEVEL | BTLF_SHOWTIMESTAMP); BT_SetLogLevel (BT_LogHandle, BTLL_VERBOSE); PCTSTR pszLogFileName = BT_GetLogFileName(BT_LogHandle);
BT_AddLogFile (pszLogFileName);
Thanks in advance Dave
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
BT_FlushLogFile() was added for a different purpose. It flushes (writes out) any unsaved records to the disk. For performance reasons, BT is trying to keep \log changes in memory and stores them only when application crashes of quits. In 99% cases you do not need to call that function explicitly and you may safely remove it from your code.
In order to clear the log, you should call BT_ClearLog(). That function removes any existing records from the log file.
BugTrapLogTest calls thins function right after opening a file:
BTTrace g_Log;
...
if (! g_Log.Open(szFullLogFileName, eLogFormat)) { ... } g_Log.SetLogFlags(BTLF_SHOWTIMESTAMP); g_Log.Clear();
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I want to change the localizaton reasource by resource dll and add some information gathering by DirectX Diagnostics tool..
I still use BugTrapU.dll , but with some additional resource dll.. is it legal for our communical product?
Thank you,
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Please change the localization of BT - I do not see any issues.
As far as additional logging - BT provides you with API that allows you to add custom log files to the report. At your convenience you may or may not use BT functions to write data to log files (check class BTTrace). But even if you use your own functions, simply call BT_AddLogFile() to attach custom log file to BT report.
You may find an example in BugTrapLogTest, it is as simple as these few lines on C++ code:
1. IF YOU USE YOUR OWN LOG FUNCTIONS:
std::ofstream ofs("C:\\my.log"); ofs << "Some message";
BT_AddLogFile("C:\\my.log");
2. IF YOU USE BT LOG FUNCTIONS:
BTTrace g_Log; g_Log.Open(_T("DirectX.log"), BTLF_TEXT); g_Log.Clear(); // call Clear() if you want to overwrite the log g_Log.Append(_T("Some message"));
and finally:
BT_AddLogFile(g_Log.GetLogFileName());
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
I was using BugTrap successfuly in my software until recently, when it seems to have just stopped working. I did not change the way I initialize bugtrap at all. The only changes were elsewhere in my code.
If I force a crash using the simple code below:
int * p = 0; *p = 55;
it appears that depending on where I put this code, I will get a bugtrap window or not. For example, if I place the crash code directly after initialization, I get the bugtrap window. But if I place the code in my Help:About handler, or almost anywhere in the main part of my program, I do not get a BugTrap window, but instead I see the standard Windows crash report about sending details to Microsoft. Do you know what is going on? I am initializing bugtrap like this:
BT_InstallSehFilter(); BT_SetSupportEMail( strReportEmail ); BT_SetFlags(BTF_DETAILEDMODE | BTF_ATTACHREPORT | BTF_EDITMAIL); BT_SetSupportURL(GUI_RESOURCE_STRING(strSupportURL)); BT_SetAppName( strAppName ); BT_SetAppVersion( strVersion ); BT_SetDialogMessage( BTDM_INTRO1, strReportSummary ); BT_SetDialogMessage( BTDM_INTRO2, strReportMessage );
Please help with any ideas. Thank you.
** UPDATE: If I call BT_CallSehFilter() in the same place as the crashing code above, then I do get the BugTrap window. Does this help?
modified on Tuesday, October 14, 2008 11:01 PM
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|