Geeks With Blogs
Malisa Ncube - .NET Delights .NET Development ideas and things

clip_image002

1. Introduction

Have you ever been in a situation where the users are unable to explain how an error was displayed on their computer and moreover describe the details of the error message? Well… I wonder why I asked when I already knew the answer you’ll say.

A few weeks ago, the some users started testing the system; I realized our method of tracking bugs was not nearly good. We had an excel spreadsheet which had bug details and how we can reproduce the bug. We had problems with that each tester was now using their own version of a bug tracking spreadsheet, since excel does not allow shared access, so I downloaded the opensource Bugtracker.NET from codeplex to see if it could be of help, since we do not have  the Team Foundation Server.

2. Trapping unhandled exceptions

The first thing to do is to catch all unhandled exceptions, and to do that you added an event handler in the Application.

Program.cs

static class Program
{

static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
....
....
Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
....
....
}


static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
Bug bug = Bug.Create();
string screenshotFile = bug.CaptureScreenShot();

bool sendScreenShot = false;
bool bugSent = false;
TaskDialog exceptionDialog = new TaskDialog();
exceptionDialog.MainIcon = TaskDialogIcon.Error;
exceptionDialog.MainInstruction = e.Exception.Message;
exceptionDialog.UseCommandLinks = false;
exceptionDialog.WindowTitle = "Error Occured!";
exceptionDialog.Content = string.Format("Unhandled Exception: {0}\nSource: {1}\nObject: {2}", e.Exception.Message, e.Exception.Source, e.Exception.TargetSite.ToString());
exceptionDialog.ExpandedByDefault = false;
exceptionDialog.ExpandedInformation = e.Exception.StackTrace;

exceptionDialog.VerificationText = "Do you want to send screenshot?";
exceptionDialog.VerificationFlagChecked = true;
exceptionDialog.FooterIcon = TaskDialogIcon.Information;

TaskDialogButton sendButton = new TaskDialogButton();
sendButton.ButtonId = 101;
sendButton.ButtonText = "Send";

TaskDialogButton cancelButton = new TaskDialogButton();
cancelButton.ButtonId = 102;
cancelButton.ButtonText = "Don't Send";

exceptionDialog.Buttons = new TaskDialogButton[] { sendButton, cancelButton };
int result = exceptionDialog.Show(null, out sendScreenShot);

if (result == sendButton.ButtonId)
{
bug.BugUrl = "http://server:88/insert_bug.aspx";
bug.MailText = string.Format("Unhandled Exception: {0}\nSource: {1}\nObject: {2}\nTrace: {3}",
e.Exception.Message, e.Exception.Source, e.Exception.TargetSite.ToString(), e.Exception.StackTrace);
bug.ProjectId = "ICEA.NET";
bug.UserName = "tester";
bug.Password = "tester";
bug.Subject = "User: [" + WindowsIdentity.GetCurrent().Name + "] "+ e.Exception.Message;

if (sendScreenShot)
bugSent = bug.WithAttachment(screenshotFile)
.ComposeMail()
.SendBugReport();
else
bugSent = bug.ComposeMail()
.SendBugReport();

if (bugSent)
MessageBox.Show("Details of error have sent to development team! Thanks.", "Message Sent", MessageBoxButtons.OK, MessageBoxIcon.Information);
else
MessageBox.Show("Could not send error details to development team!", "Message Failure", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}


}

The above code snippet will ensure that if an exception is unhandled then the method Application_ThreadException will be executed and the exception details are passed as an argument.

3. Capturing the screenshot

This is a very important part, because the screenshot will be attached to the email which is then sent to the server, so we can know what the user was doing when the exception occurred. The image is then converted to base64 format. This is simply changing the image to text so we can send it over HTTP.


public string ImageToBase64(Image image, System.Drawing.Imaging.ImageFormat format)
{
using (MemoryStream ms = new MemoryStream())
{
// Convert Image to byte[]
image.Save(ms, format);
byte[] imageBytes = ms.ToArray();

// Convert byte[] to Base64 String
string base64String = Convert.ToBase64String(imageBytes);
return base64String;
}
}

private string CaptureImage(Point SourcePoint, Point DestinationPoint, Rectangle SelectionRectangle)
{
using (Bitmap bitmap = new Bitmap(SelectionRectangle.Width, SelectionRectangle.Height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(SourcePoint, DestinationPoint, SelectionRectangle.Size);
}
//return the string which represent the image
return ImageToBase64(bitmap, ImageFormat.Jpeg);
}
}

public string CaptureScreenShot()
{
Rectangle bounds = Screen.GetBounds(Screen.GetBounds(Point.Empty));
return CaptureImage(Point.Empty, Point.Empty, bounds);
}

4. Composing the Bug Mail

public Bug ComposeMail()
{
mail = "&username=" + HttpUtility.UrlEncode(_UserName) +
"&password=" + HttpUtility.UrlEncode(_Password) +
"&from=" + HttpUtility.UrlEncode(_UserName) +
"&short_desc=" + HttpUtility.UrlEncode(_Subject) +
"&projectid=" + HttpUtility.UrlEncode(_ProjectId);

if (_Attachment != string.Empty)
mail += "&message=" + HttpUtility.UrlEncode(_Attachment);
else
mail += "&message=" + HttpUtility.UrlEncode(_MailText);

return this;
}

5. Making the Web Request (HTTP)

Thanks to fiddler, I was able to analyse the details of the contents that are posted to the Bugtracker.NET. The tool downloadable with BugTracker.NET called bt2312 is written in C++. I translated part of it to C# and luckily .NET has very interesting libraries which allow you to perform most of the things out of the box.

clip_image006

Fiddler enables you to inspect your web requests and that was helpful, because after i inspected the web requests from bt2312 i was able to replicate the behaviour.

clip_image008

The labels above indicate the steps that have been made during the web request.

1. The application sends the data using HTTP.

2. The data sent (as text).

3. The response.

public bool SendBugReport()
{
bool Success = false;
ASCIIEncoding encoding = new ASCIIEncoding();


byte[] buffer = encoding.GetBytes(mail);

// Prepare web request...
HttpWebRequest myRequest =
(HttpWebRequest)WebRequest.Create(_BugUrl);

// We use POST ( we can also use GET )

myRequest.Method = "POST";

// Set the content type to a FORM
myRequest.ContentType = "application/x-www-form-urlencoded";
myRequest.UserAgent = Application.ProductName;
// Get length of content
myRequest.ContentLength = buffer.Length;

// Get request stream
Stream newStream = myRequest.GetRequestStream();

// Send the data.
newStream.Write(buffer, 0, buffer.Length);

// Close stream
newStream.Close();


// Assign the response object of 'HttpWebRequest' to a 'HttpWebResponse' variable.
HttpWebResponse myHttpWebResponse = (HttpWebResponse)myRequest.GetResponse();

// Display the contents of the page to the console.
Stream streamResponse = myHttpWebResponse.GetResponseStream();

// Get stream object
StreamReader streamRead = new StreamReader(streamResponse);
Char[] readBuffer = new Char[256];

// Read from buffer
int count = streamRead.Read(readBuffer, 0, 256);

while (count > 0)
{
// get string
String resultData = new String(readBuffer, 0, count);
// Write the data
Success = resultData.Contains("OK:");
Console.WriteLine(resultData);
// Read from buffer
count = streamRead.Read(readBuffer, 0, 256);

}
// Release the response object resources.
streamRead.Close();
streamResponse.Close();

// Close response
myHttpWebResponse.Close();

return Success;
}


I have attached the Bug.cs class which contains all the code for creating a Bug report and sending it to and BugTracker.NET server. Apologies, i have not put a lot of comments in my code, if i revise this post i will probably do something about it.

Download Bug.cs

Posted on Tuesday, May 26, 2009 12:43 PM | Back to top


Comments on this post: Catching unhandled exceptions and sending them to BugTracker.NET

# re: Catching unhandled exceptions and sending them to BugTracker.NET
Requesting Gravatar...
Hi.
This post is very useful!
The file: Bug.cs is missing. Can you upload it again?

Thanks.
Left by Glauco on Aug 24, 2009 11:30 AM

# re: Catching unhandled exceptions and sending them to BugTracker.NET
Requesting Gravatar...
I have sent you the file by mail. I am looking into re-uploading the file onto the blog.

Thanks
Left by Malisa Ncube on Aug 24, 2009 6:12 PM

# re: Catching unhandled exceptions and sending them to BugTracker.NET
Requesting Gravatar...
I'm also looking for the file, could you send me the file by mail, too?
Left by Jean on Jan 15, 2010 3:24 AM

# re: Catching unhandled exceptions and sending them to BugTracker.NET
Requesting Gravatar...
Could you send me the Bug.cs by mail, too?
Left by Rafal on Oct 18, 2010 1:43 AM

# re: Catching unhandled exceptions and sending them to BugTracker.NET
Requesting Gravatar...
Could you send me the Bug.cs by mail, too?
Left by Alexandre Carvalho on Nov 30, 2010 4:52 AM

# re: Catching unhandled exceptions and sending them to BugTracker.NET
Requesting Gravatar...
Very cool.

Two things: First, could you please send me the bug.cs file? Second, was this developed for a website or a desktop application?
Left by Michael Bielski on Dec 28, 2010 3:38 AM

# re: Catching unhandled exceptions and sending them to BugTracker.NET
Requesting Gravatar...
I'd like to have the file too, the download link is no longer working. Thanks!
Left by michaels coupons on Jun 04, 2011 12:23 AM

# re: Catching unhandled exceptions and sending them to BugTracker.NET
Requesting Gravatar...
Please send me the Bug.cs file or upload again.
Left by Vasanth on Nov 01, 2011 12:44 AM

# re: Catching unhandled exceptions and sending them to BugTracker.NET
Requesting Gravatar...
Hi!
Fantastic idea !
Could you please send me the source file ?
Many thanks
Left by NinjaCross on Nov 11, 2011 3:13 AM

# re: Catching unhandled exceptions and sending them to BugTracker.NET
Requesting Gravatar...
Did anyone ever receive the Bug.cs file or was it uploaded somewhere? I would like to get it.
Left by Adrian on Aug 09, 2012 9:03 AM

# re: Catching unhandled exceptions and sending them to BugTracker.NET
Requesting Gravatar...
Download Bug.cs from

https://skydrive.live.com/?cid=dac24aabcbbee919#cid=DAC24AABCBBEE919&id=DAC24AABCBBEE919!119
Left by Malisa Ncube on Aug 09, 2012 7:13 PM

Your comment:
 (will show your gravatar)


Copyright © Malisa L. Ncube | Powered by: GeeksWithBlogs.net