Click here to Skip to main content
12,299,086 members (50,418 online)
Click here to Skip to main content

Stats

209.5K views
1.5K downloads
188 bookmarked
Posted

A Treatise on Using Debug and Trace classes, including Exception Handling

, 12 Oct 2002
C#'s built in Debug and Trace classes can be confusing and inappropriately used. This article looks at one success story using debug traces and assertions, and presents an improved debug class.
using System;
using System.Collections;
using System.Diagnostics;
using System.Windows.Forms;

namespace MyApp	// change this namespace as you wish
{
	// The problem/reason dictionary key type
	public class DbgKey
	{
		private string key;
		
		public string Name
		{
			get {return key;}
			set {key=value;}
		}
		
		public DbgKey(string s)
		{
			key=s;
		}
	}
	
	// The problem/reason object
	public class ProblemReason
	{
		string problem;
		string[] reasons;

		public ProblemReason(string s1, string[] s2)
		{
			problem=s1;
			reasons=s2;
		}
			
		public string GetProblem()
		{
			return problem;
		}
			
		public string[] GetReasons()
		{
			return reasons;
		}
	}

	// the problem/reason collection
	public class DbgProblemCollection
	{
		private SortedList probs;
		
		public DbgProblemCollection()
		{
			probs=new SortedList();
		}
		
		public void Add(DbgKey key, string problem, string[] reasonList)
		{
			probs.Add(key.Name, new ProblemReason(problem, reasonList));
		}
		
		public bool Contains(DbgKey key)
		{
			return probs.Contains(key.Name);
		}
		
		public int Count
		{
			get
			{
				return probs.Count;
			}
		}
		
		public ProblemReason this[DbgKey key]
		{
			get
			{
				return (ProblemReason)probs[key.Name];
			}
		}
	}
	
	public class Dbg
	{
		// The debug extensions:
		private static DbgProblemCollection problems=new DbgProblemCollection();
	
		// return the problem/reason collection
		public static DbgProblemCollection Problems
		{
			get {return problems;}
		}

		[Conditional("TRACE")]
		public static void InitializeUnhandledExceptionHandler()
		{
			AppDomain.CurrentDomain.UnhandledException+=new UnhandledExceptionEventHandler(DbgExceptionHandler);
		}

		public static void DbgExceptionHandler(object sender, UnhandledExceptionEventArgs args)
		{
			Exception e=(Exception) args.ExceptionObject;
			Trace.WriteLine("Exception: "+e.Message);
			MessageBox.Show(
				"A fatal problem has occurred.\n"+e.Message,
				"Program Stopped",
				MessageBoxButtons.OK,
				MessageBoxIcon.Stop,
				MessageBoxDefaultButton.Button1);
			Trace.Close();
			Process.GetCurrentProcess().Kill();
		}
		
		// The Warn method is enabled in release mode
		[Conditional("TRACE")]
		public static void Warn(bool b, DbgKey key)
		{
			Trace.WriteLine("Warning: "+key.Name);
			if (problems.Contains(key))
			{
				string explanation=GetExplanation(key);
				MessageBox.Show(
					explanation,
					"Warning",
					MessageBoxButtons.OK,
					MessageBoxIcon.Warning,
					MessageBoxDefaultButton.Button1);
			}
			else
			{
				MessageBox.Show(
					"A problem has occurred that should be corrected.\n\nReference: "+key.Name,
					"Warning",
					MessageBoxButtons.OK,
					MessageBoxIcon.Warning,
					MessageBoxDefaultButton.Button1);
			}
		}

		// The Assert method is enabled in release mode
		[Conditional("TRACE")]
		public static void Assert(bool b, DbgKey key)
		{
			Trace.WriteLine("Assert: "+key.Name);
			if (problems.Contains(key))
			{
				string explanation=GetExplanation(key);
				MessageBox.Show(
					explanation,
					"Program Stopped",
					MessageBoxButtons.OK,
					MessageBoxIcon.Stop,
					MessageBoxDefaultButton.Button1);
			}
			else
			{
				MessageBox.Show(
					"A fatal problem has occurred.\n\nReference: "+key.Name,
					"Program Stopped",
					MessageBoxButtons.OK,
					MessageBoxIcon.Stop,
					MessageBoxDefaultButton.Button1);
			}
			Trace.Close();
			Process.GetCurrentProcess().Kill();
		}

		[Conditional("DEBUG")]
		public static void LogOutput(string fn)
		{
			Debug.Listeners.Add(new TextWriterTraceListener(fn));
			DateTime dt=DateTime.Now;
			Debug.WriteLine("Debug Logging Initialized: "+dt.ToString());
		}

		// Flag the debugger to break at the next instruction.
		[Conditional("DEBUG")]
		public static void Break()
		{
			Debugger.Break();
		}

		// Put together the list of possible reasons for the particular problem.
		private static string GetExplanation(DbgKey key)
		{
			ProblemReason ps=problems[key];
			string explanation=ps.GetProblem()+"\n\nPossible reasons:\n\n";
			int n=1;
			foreach (string sol in ps.GetReasons())
			{
				explanation+="  "+n.ToString()+". "+sol+"\n";
				++n;
			}
			return explanation;
		}

		/*
		 * Mirror the current Debug and Trace class functionality.
		 */
		
		public static bool AutoFlush
		{
			get {return Debug.AutoFlush;}
			set {Debug.AutoFlush=value;}
		}
		
		public static int IndentLevel
		{
			get {return Debug.IndentLevel;}
			set {Debug.IndentLevel=value;}
		}
		
		public static int IndentSize
		{
			get {return Debug.IndentSize;}
			set {Debug.IndentSize=value;}
		}
		
		public static TraceListenerCollection Listeners
		{
			get {return Trace.Listeners;}
		}
		
		[Conditional("TRACE")]
		public static void Assert(bool b)
		{
			Trace.Assert(b);
		}
		
		[Conditional("TRACE")]
		public static void Assert(bool b, string s)
		{
			Trace.Assert(b, s);
		}
		
		[Conditional("TRACE")]
		public static void Assert(bool b, string s1, string s2)
		{
			Trace.Assert(b, s1, s2);
		}

		[Conditional("TRACE")]
		public static void Fail(string s)
		{
			Trace.Fail(s);
		}
		
		[Conditional("TRACE")]
		public static void Fail(string s1, string s2)
		{
			Trace.Fail(s1, s2);
		}
		
		[Conditional("DEBUG")]		
		public static void Close()
		{
			Trace.Close();
		}
		
		[Conditional("DEBUG")]		
		public static void Flush()
		{
			Debug.Flush();
		}
		
		[Conditional("DEBUG")]		
		public static void Indent()
		{
			Debug.Indent();
		}
		
		[Conditional("DEBUG")]		
		public static void Unindent()
		{
			Debug.Unindent();
		}
		
		// Write
		
		[Conditional("DEBUG")]
		public static void Write(object obj)
		{
			Debug.Write(obj);
		}
		
		[Conditional("DEBUG")]		
		public static void Write(string s)
		{
			Debug.Write(s);
		}
		
		[Conditional("DEBUG")]		
		public static void Write(object obj, string s)
		{
			Debug.Write(obj, s);
		}
		
		[Conditional("DEBUG")]		
		public static void Write(string s1, string s2)
		{
			Debug.Write(s1, s2);
		}
		
		// WriteIf
		
		[Conditional("DEBUG")]		
		public static void WriteIf(bool b, object obj)
		{
			Debug.WriteIf(b, obj);
		}
		
		[Conditional("DEBUG")]		
		public static void WriteIf(bool b, string s)
		{
			Debug.WriteIf(b, s);
		}
		
		[Conditional("DEBUG")]		
		public static void WriteIf(bool b, object obj, string s)
		{
			Debug.WriteIf(b, obj, s);
		}
		
		[Conditional("DEBUG")]		
		public static void WriteIf(bool b, string s1, string s2)
		{
			Debug.WriteIf(b, s1, s2);
		}
		
		// WriteLine
		
		[Conditional("DEBUG")]		
		public static void WriteLine(object obj)
		{
			Debug.WriteLine(obj);
		}
		
		[Conditional("DEBUG")]		
		public static void WriteLine(string s)
		{
			Debug.WriteLine(s);
		}
		
		[Conditional("DEBUG")]		
		public static void WriteLine(object obj, string s)
		{
			Debug.WriteLine(obj, s);
		}
		
		[Conditional("DEBUG")]		
		public static void WriteLine(string s1, string s2)
		{
			Debug.WriteLine(s1, s2);
		}
		
		// WriteLineIf
		
		[Conditional("DEBUG")]		
		public static void WriteLineIf(bool b, object obj)
		{
			Debug.WriteLineIf(b, obj);
		}
		
		[Conditional("DEBUG")]		
		public static void WriteLineIf(bool b, string s)
		{
			Debug.WriteLineIf(b, s);
		}
		
		[Conditional("DEBUG")]		
		public static void WriteLineIf(bool b, object obj, string s)
		{
			Debug.WriteLineIf(b, obj, s);
		}
		
		[Conditional("DEBUG")]		
		public static void WriteLineIf(bool b, string s1, string s2)
		{
			Debug.WriteLineIf(b, s1, s2);
		}
		
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Marc Clifton
United States United States
Marc is the creator of two open source projects, MyXaml, a declarative (XML) instantiation engine and the Advanced Unit Testing framework, and Interacx, a commercial n-tier RAD application suite.  Visit his website, www.marcclifton.com, where you will find many of his articles and his blog.

Marc lives in Philmont, NY.

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160525.2 | Last Updated 13 Oct 2002
Article Copyright 2002 by Marc Clifton
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid