Skip to content

April 19, 2009

C# Crash report – How to handle remote crash report with HTTP POST

Objective: Make your applications report any unhandled crash to a database on a remote server.
Description:You have a Reporter class that will send the values to page accepting POST data. The application main entry point will be surrounded by a Try Catch block (effectively catching every possible unhandled errors in the application). It will then try to send the stack trace of the error to the webpage. If it can’t (ie. no internet connection, server down) it won’t do anything and the application quits.

It can be very useful to catch those bugs you didn’t see or thought possible without mass testing and QA…which, let’s face it, you can’t afford as a self programmer. Your users are your testers! :P
A word of caution though, you might want to warn your users you’re sending data, and what kind of data you’re sending before using this. In this example, it doesn’t warn the end user.

On to the code below the break!

Reporter.cs

You need to add a reference (Projet->Add Reference…->System.Web) so you can access the urlencoder

using System;
using System.IO;
using System.Net;
using System.Text;
 
namespace ErrorReport
{
 
    //shamelessly copied from http://msdn.microsoft.com/en-us/library/debx8sh9.aspx
    class Reporter
    {
 
        private WebRequest request;
        private string postData;
 
        public Reporter (string url)
	{
            // Create a request using a URL that can receive a post.
            request = WebRequest.Create (url);
            // Set the Method property of the request to POST.
            request.Method = "POST";
            // Set the ContentType property of the WebRequest.
            request.ContentType = "application/x-www-form-urlencoded";
            postData = "";
 
	}
        /// 
        /// Add an combination of key/value to post to the server
        /// 
        ///
the identifier you'll use while retrieving the POST data
        ///
value of the POST for that key
        public void AddItem(string key, string value)
        {
            postData += "&" + key + "=" + System.Web.HttpUtility.UrlEncode(value);
            //clean up so we make sure it doesn't start with a &
            postData.TrimStart('&');
        }
        public void Post()
        {
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);
            // Set the ContentLength property of the WebRequest.
            request.ContentLength = byteArray.Length;
            // Get the request stream.
            Stream dataStream = request.GetRequestStream();
            // Write the data to the request stream.
            dataStream.Write(byteArray, 0, byteArray.Length);
            // Close the Stream object.
            dataStream.Close();
            // Get the response.
            WebResponse response = request.GetResponse();
            // Display the status.
            Console.WriteLine(((HttpWebResponse)response).StatusDescription);
            // Get the stream containing content returned by the server.
            dataStream = response.GetResponseStream();
            // Open the stream using a StreamReader for easy access.
            StreamReader reader = new StreamReader(dataStream);
            // Read the content.
            string responseFromServer = reader.ReadToEnd();
            // Display the content.
            Console.WriteLine(responseFromServer);
            // Clean up the streams.
            reader.Close();
            dataStream.Close();
            response.Close();
 
        }
 
    }
}

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Windows.Forms;
 
namespace ErrorReport
{
    static class Program
    {
        /// 
        /// The main entry point for the application.
        /// 
        [STAThread]
        static void Main()
        {
            Reporter r = new Reporter("http://example.com/postDataHandler.php");
 
            try
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
 
            }
            catch (Exception e)
            {
                try
                {
                    //Now i add my post items. in this example, they will be retrieved as such:
                    //$_POST["ERRORMSG"] and $_POST["STACKTRACE"]
                    //Of course this is entirely customizable to your need!
                    r.AddItem("ERRORMSG", e.Message);
                    r.AddItem("STACKTRACE", e.StackTrace);
                    r.Post();
                }
                catch (Exception)
                {
                }
                finally
                {
                    MessageBox.Show("A fatal error has occured, the application will now be terminated","ERROR",MessageBoxButtons.OK,MessageBoxIcon.Error);
                    Application.Exit();
                }
 
            }
 
        }
    }
}

So this is the C# code. As you can see it’s pretty simple! if anything crashes in the form1, it will be reported and posted to http://example.com/postDataHandler.php

I created a very simple table on my database to handle the storing of those infos

errorReport.sql

DROP TABLE IF EXISTS `errorReport`;
CREATE TABLE IF NOT EXISTS `errorReport` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `errormsg` varchar(255) NOT NULL,
  `stacktrace` text NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

the code above will create the MySQL table, now on the code of postDataHandler.php!

postDataHandler.php

 

And there you go! Everytime the application crashes it will send the stacktrace to your MySQL server. Of course, it can be very easily adapted to your needs, and works exactly the same way is ASP. If it’s for an intranet use, then you just need to adapt the Reporter.cs to use a dataAdapter and a MSSQL server. There is no need to use POST in this situation. This is more useful for programmers like me who have a homepage, but whose software can be use by anyone around the world.

Enjoy yourself!

Read more from C#

Share your thoughts, post a comment.

You must be logged in to post a comment.