The best answer is: don't. There's already a system for doing this built right into the operating system.
If you let the exceptions "bubble up" and out of the program, modern OS'es include Windows Error Reporting, which will give the user the option of sending an error report to Microsoft. (Note: do not send error reports automatically - think long and hard about the legal ramifications regarding privacy laws...)
The error report includes not just the exception information and full stack trace, but also includes a good portion of your process' memory, as well as exactly which OS modules were loaded (so you can even tell whether the client had a relevant Windows Update patch applied). It wraps up all of this information into a minidump file (and also includes a few XML files with additional info).
This error report is uploaded to Microsoft's servers, so you don't have to worry about setting up and maintaining a "call home" server. All error reports for your programs are categorized using advanced heuristics into "buckets", with each "bucket" containing reports that are likely to be caused by the same bug.
Microsoft exposes all of this information to you (as the software publisher) through a site called Winqual. Using Winqual, you can examine all of the error reports, and use their heuristical bucketizing algorithms to decide which bugs are most impacting your customers. You can also download each individual report for more detailed investigation.
If you have a symbol server and source control server set up in your organization (and you certainly should), then you can just load the minidump from a downloaded error report right into Visual Studio, and it will automagically check the old source out of source control and allow you to inspect the exact state of the program at the moment it crashed.
Finding and fixing bugs has never been this easy.
To summarize, here's what you need to do:
- Set up a symbol server and a source server in your organization. Establish a release policy to ensure that all releases get source-indexed pdbs added to the symbol server before they get released to the customer.
- Establish an account with Winqual. You'll need an Authenticode code-signing certificate; if you get a non-VeriSign code-signing cert, then you'll also have to spend $100 for an "organizational certificate" from VeriSign.
- Modify your release policy to include creating mapping files for your releases. These mapping files are uploaded to Winqual before shipping the release.
- Do not catch unexpected exceptions. If you do ever need to catch them, be sure to rethrow using
throw
and not throw ex
, so the stack trace and original program state is preserved.
For more information, I can highly recommend Debugging .NET 2.0 Applications by John Robbins. In spite of the "2.0" in the title, this book is still completely relevant today (except that the only source server example is using Visual SourceSafe, which was a complete joke even back then). Another good book if you need to do a lot of debugging is Advanced .NET Debugging, though it is starting to show its age, especially since the new VS2010 debugging advancements make a lot of its techniques out of date.