| crashrpt |
A crash reporting system for Windows applications

# Using CrashRpt API

CrashRpt library provides several API functions, structures and classes that can be used in your project (see CrashRpt Functions, CrashRpt Structures, CrashRpt Wrapper Classes).

Note:
  Older versions of CrashRpt provided different set of API functions that are now declared obsolete. Those obsolete API functions are still supported for compatibility with older versions of CrashRpt, but it is recommended that you use the newer functions instead. Here is the complete list of Obsolete Functions.

All CrashRpt functions have `cr` prefix, CrashRpt structures have `CR` prefix and CrashRpt classes have `Cr` prefix.

All CrashRpt functions using character set dependent arguments have two versions of function name (multibyte versions are A-suffixed and wide character versions are W-suffixed). For example, crInstall() function has two versions of function name: crInstallA() and crInstallW(). Typically in your program you use a character set independent mapping of function name, for example use crInstall() that expands into crInstallW() if you use wide character set or into crInstallA() if you use multibyte character set.

## Enabling Crash Reporting

To enable crash reporting support in your C++ application you use crInstall() and crInstallToCurrentThread2() functions. There are two functions because of difference in work of exception handlers. Some of them work for entire process and others work for caller thread only.

The function crInstall() installs exception handlers that work on per-process basis. Typically you call the crInstall() in the beginning of your main() or WinMain() function.

You pass configuration settings to crInstall() through the CR_INSTALL_INFO structure. The configuration settings include application name and version, recipient's e-mail address or URL, path for saving error reports, Privacy Policy URL and so on.

You can also create a crash callback function LPGETLOGFILE() and pass its pointer to crInstall(). The crash callback function is called on crash.

On application exit, you use the crUninstall() function to unset exception handlers.

The function crInstallToCurrentThread2() installs exception handlers that work on per-thread basis. In a multi-threaded program you call the crInstallToCurrentThread2() for all threads except the main one. Typically you call this function in the beginning of the thread procedure.

Just before the return from the thread procedure, call the crUninstallFromCurrentThread() function to unset exception handlers from the caller thread. No need to call the crUninstallFromCurrentThread() function in the main execution thread, because crUninstall() will do that for you automatically.

You can use CrashRpt Wrapper Classes to simplify installation and uninstallation of exception handlers in your program. Use CrAutoInstallHelper wrapper class to install exception handlers in your main() function. In a multi-threaded program, use CrThreadAutoInstallHelper wrapper class to install exception handlers in each worker thread.

## Adding a Custom File

Typically an application creates and maintains a log file where operations and errors are written. Such a log file can be helpful for crash analysis and should be added to your application's error report. You add application-specific files to the error report using crAddFile2() function.

## Adding a Custom Property

One way to add application-defined info to the error report is adding a file as described above. But sometimes you may want to extend the crash description XML file by adding a named literal property to the file. You can do this through the crAddProperty() function.

For example, you may need to add the info about the amount of free disk space on a specific disk drive at the moment of crash, or about the version of the graphics card driver.

## Adding a Screen Shot

It may be useful to have a screen shot of user's desktop at the moment of crash. This may help to see which button user clicked before the crash, to see the desktop state and easier reproduce the crash. For example, for multi-monitor desktops it may be useful to see if the application window is positioned on the primary monitor, on the secondary monitor, or at the boundary of two monitors. Sometimes it may be enough to see only the region of the desktop occupied by your application and not the rest of desktop.

But there is one thing to take in account. By enabling screenshot capture, you should be careful about user's privacy. Some parts of the desktop screenshot may contain private or user identifying information: folder names, wallpapers, photos, text fragments and so on. That's why you should always provide a link to your Privacy Policy page describing what information you collect on crash and what purposes you use it for. By clicking the Send Report button, user confirms he/she is familiar with the contents of the error report and accepts the terms of the Privacy Policy.

You can make a screen shot of user's virtual screen or a screen shot of your main window using the crAddScreenshot() function.

## Adding a Registry Key

Many applications store settings inside of Windows registry. Application's settings might be useful for crash analysis. Since v.1.2.6, you can ask CrashRpt to dump a registry key contents on crash. Use the crAddRegKey() function.

## Debugging a Remote Logics Error

Sometimes it is required to remotely debug some application logics error. Such an error, for example, infinite loop in a worker thread, may not cause program crash. To collect the information about error that doesn't cause crash, a software developer might provide an ability to generate error report manually on user demand, for example on a key combination press. The crGenerateErrorReport() function allows to generate an error report manually.

## Silent (non-GUI) Mode

Since v.1.2.2, CrashRpt can function in silent mode. In this mode, no Error Report window is shown on crash and no interaction with user is performed. The silent mode is enabled by specifying the CR_INST_NO_GUI flag for CR_INSTALL_INFO::dwFlags structure member.

The silent mode is designed for server applications or services that do not need to interact with user on crash. The silent mode should not be used for regular GUI applications. For regular interactive applications, a user should provide his/her consent to allow sending the error report.

## Automatic Application Restart

Since v.1.2.4, you can tell CrashRpt to restart your application automatically when crash occurs. This can be done by specifying the CR_INST_APP_RESTART flag for the CR_INSTALL_INFO::dwFlags structure member.

You can pass command line parameters to the executable being restarted using CR_INSTALL_INFO::pszRestartCmdLine, but can't specify another executable for restart. Only the same executable can be restarted that was used to start the current process.

The application is restarted only if at least 60 seconds have elapsed since its start up. This is done to avoid cyclic restarts of an application that crashes right on its start up. Also, the application is restarted only if the user does provide his/her consent.

If you generate an error report manually, the caller process is not terminated automatically. If you do not want to terminate the caller process, and want to avoid starting the second instance of the application, specify the CR_EXCEPTION_INFO::bManual flag.

## Testing If Exceptions are Intercepted

When you install crash reporting support to your program, it is important to test if CrashRpt intercepts exceptions properly. Use crEmulateCrash() function to emulate an exceptional situation. You may call this function in each thread of your program to ensure all exceptions will be caught.

## Getting Error Messages

Typically a CrashRpt API function returns zero value if succeeded and non-zero if failed. To get text error message of the last called function, use crGetLastErrorMsg().

## CrashRpt API Reference

- CrashRpt Functions
- CrashRpt Structures
- CrashRpt Wrapper Classes
- Obsolete Functions

## FAQ

I need to modify some crashrpt configuration info (i.e. uPriorities) based on information collected after crInstall(). What is the best way ?

Currently, there are no ways to modify the CrashRpt configuration info after calling crInstall(). It is recommend to hardcode the info you pass to crInstall() function, that means not reading it from an INI file or from another source.

However, if you strongly wish to read crashrpt configuration info from an external file, call crInstall() after reading the info from that file. Simple file reading functionality is not likely to crash. So the probability you miss a crash while reading the file is small.

We ship a software (game etc.) and certain crashes only happen on certain hardware. So we need some sort of functionality that gathers GPU/CPU/general hardware information upon crash report generation. What do we do?

We introduced a function crAddProperty() specially for purposes of extending the crash description XML as you wish. You can also use the crAddFile2() function, which allows to add a user-defined file to the crash report.

I want to uniquely identify the installation by what the error reports are sent. What do I do?

In CrashRpt v.1.2.1, we introduced a function crAddProperty() specially for purposes of extending the crash description XML as you wish. You can create the installation GUID in your program, store it in the registry or in a file and pass this GUID to the crAddProperty() function, so the named property will be added to the crashrpt.xml and you will be able to identify the installation and associate the bugs together.

The following code example shows how to do this (code provided by tdev):

      // ... upon program start, check if GUID is not existing, if not create one:
      GUID *g = new GUID();
      CoCreateGuid(g);

      char buf[120];
      sprintf( buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
        g->Data1, g->Data2, g->Data3, UINT(g->Data4[0]), UINT(g->Data4[1]), UINT(g->Data4[2]),
        UINT(g->Data4[3]), UINT(g->Data4[4]), UINT(g->Data4[5]), UINT(g->Data4[6]), UINT(g->Data4[7]));
      delete g;
      std::string guid = std::string(buf);

      //... later, add it to the crashreport:
      crAddProperty("SystemGUID", guid);

My software's worker thread hangs up on user's machine (but no crash happens). How do I debug the problem?

To collect information about such error, you may provide an ability to generate error report manually, for example on a key combination press. When the key combination is pressed, generate error report manually using crGenerateErrorReport() function.

What is the minidump type? What minidump type should I use?

The minidump type defines what information is contained in the minidump. The default minidump type is MiniDumpNormal. However, the MiniDumpNormal type contains only essential info required to recover the stack traces for each thread. To recover the state of global variables, other minidump types should be used. For additional info, see the Effective Minidumps article.