A long time ago, I posted a VB version of this code and thought I would post the C# version since I have gotten several requests. I have not tested it too extensively yet, but it is working so far. I had to remove the XML documentation comments for posting here.
I have made some improvements over the VB version, but not significantly. Eventually I will be posting the whole project structure to CodeProject.
using System;
using System.Text;
using System.Runtime.Serialization;
namespace Kobra.Error
{
[Serializable]
public class KobraException : System.Exception
{
#region Class Data
private string appDomainName;
private string assemblyName;
private string currentProcessID;
private string currentThreadID;
private string currentThreadUser;
private string machineName;
private System.DateTime dateTimeUTC;
private string windowsIdentity;
// Collection provided to store any extra information associated with the exception
private System.Collections.Specialized.NameValueCollection additionalInformation;
// These provide some code simplifications below
private string newLine = Environment.NewLine;
private string errorPermissionDenied = "Permission Denied";
private string errorInfoAccessException = "Information could not be accessed.";
private System.Type dateTimeType = System.Type.GetType("DateTime");
private System.Type stringType = System.Type.GetType("String");
private System.Type collectionType = System.Type.GetType("NameValueCollection");
#endregion
#region Constructors
public KobraException() : base()
{
try
{
this.assemblyName = System.Reflection.Assembly.GetCallingAssembly().FullName;
}
catch (System.Security.SecurityException)
{
this.assemblyName = this.errorPermissionDenied;
}
catch
{
this.assemblyName = this.errorInfoAccessException;
}
// Set up our variables and log it
this.Initialize();
this.DoLogging(string.Empty);
}
public KobraException(string message) : base(message)
{
// "message" may be null since the base class handles null by substituting the class name.
try
{
this.assemblyName = System.Reflection.Assembly.GetCallingAssembly().FullName;
}
catch (System.Security.SecurityException)
{
this.assemblyName = this.errorPermissionDenied;
}
catch
{
this.assemblyName = this.errorInfoAccessException;
}
// Set up our variables and log it
this.Initialize();
this.DoLogging(String.Empty);
}
public KobraException(string message, System.Exception innerException) : base(message, innerException)
{
// "message" may be null since the base class handles null by substituting the class name.
// "innerException" may be null since there may be cases when this constructor is called, but the
// inner exception is optional.
try
{
this.assemblyName = System.Reflection.Assembly.GetCallingAssembly().FullName;
}
catch (System.Security.SecurityException)
{
this.assemblyName = this.errorPermissionDenied;
}
catch
{
this.assemblyName = this.errorInfoAccessException;
}
// Set up our variables and log it
this.Initialize();
this.DoLogging(string.Empty);
}
protected KobraException(SerializationInfo info, StreamingContext context) : base(info, context)
{
// Only test for info being null since that is all that Microsoft tests for.
// Throw the exception here to get it out as soon as it is discovered.
if (info == null)
throw new ArgumentNullException("info");
// Set up our variables
this.Initialize();
// Deserialize our custom properties after Initialize and before logging
this.dateTimeUTC = info.GetDateTime("kobraDateTime").ToUniversalTime();
this.appDomainName = info.GetString("kobraAppDomainName");
this.assemblyName = info.GetString("kobraAssemblyName");
this.currentProcessID = info.GetString("kobraCurrentProcessID");
this.currentThreadID = info.GetString("kobraCurrentThreadID");
this.currentThreadUser = info.GetString("kobraCurrentThreadUser");
this.machineName = info.GetString("kobraMachineName");
this.windowsIdentity = info.GetString("kobraWindowsIdentity");
this.additionalInformation = (System.Collections.Specialized.NameValueCollection)
(info.GetValue("additionalInformation", this.collectionType));
this.DoLogging(String.Empty);
}
#endregion
#region Overrides
[System.Security.Permissions.SecurityPermission(
System.Security.Permissions.SecurityAction.Demand,
SerializationFormatter=true)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
// Serialize our custom properties
info.AddValue("kobraDateTime", this.dateTimeUTC.ToLocalTime(), this.dateTimeType);
info.AddValue("kobraAppDomainName", this.appDomainName, this.stringType);
info.AddValue("kobraAssemblyName", this.assemblyName, this.stringType);
info.AddValue("kobraCurrentProcessID", this.currentProcessID, this.stringType);
info.AddValue("kobraCurrentThreadID", this.currentThreadID, this.stringType);
info.AddValue("kobraCurrentThreadUser", this.currentThreadUser, this.stringType);
info.AddValue("kobraMachineName", this.machineName, this.stringType);
info.AddValue("kobraWindowsIdentity", this.windowsIdentity, this.stringType);
info.AddValue("kobraAdditionalInformation", this.additionalInformation, this.collectionType);
// Call the base routine
base.GetObjectData(info, context);
}
public override string ToString()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder(128);
// Make sure we get the standard output
sb.Append(base.ToString());
// Since the standard output can be nothing, we only add our variables when necessary
if (sb.Length > 0)
{
// Change this format as required
sb.Append(this.newLine + this.newLine);
sb.Append("Local Date Time: " + this.dateTimeUTC.ToLocalTime().ToString() + this.newLine);
sb.Append("Windows Identity: " + this.windowsIdentity + this.newLine);
sb.Append("Machine Name: " + this.machineName + this.newLine);
sb.Append("App Domain Name: " + this.appDomainName + this.newLine);
sb.Append("Assembly Name: " + this.assemblyName + this.newLine);
sb.Append("Current Process ID: " + this.currentProcessID + this.newLine);
sb.Append("Current Thread ID: " + this.currentThreadID + this.newLine);
sb.Append("Current Thread User: " + this.currentThreadUser + this.newLine);
// Additional info collection special handling
if (this.additionalInformation.Count > 0)
{
sb.Append("Additional Information: " + this.currentThreadUser + this.newLine);
foreach (string s in this.additionalInformation.AllKeys)
{
sb.Append(" " + s);
if (this.additionalInformation.Get(s).Length > 0)
{
sb.Append(" = " + this.additionalInformation.Get(s));
}
sb.Append(this.newLine);
}
}
}
return sb.ToString();
}
#endregion
#region Private Routines
private void Initialize()
{
this.dateTimeUTC = System.DateTime.UtcNow;
// **************************************************
try
{
this.appDomainName = System.AppDomain.CurrentDomain.FriendlyName;
}
catch (System.Security.SecurityException)
{
this.appDomainName = this.errorPermissionDenied;
}
catch
{
this.appDomainName = this.errorInfoAccessException;
}
// **************************************************
try
{
this.currentProcessID = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
}
catch (System.Security.SecurityException)
{
this.currentProcessID = this.errorPermissionDenied;
}
catch
{
this.currentProcessID = this.errorInfoAccessException;
}
// **************************************************
try
{
this.currentThreadID = AppDomain.GetCurrentThreadId().ToString();
}
catch (System.Security.SecurityException)
{
this.currentThreadID = this.errorPermissionDenied;
}
catch
{
this.currentThreadID = this.errorInfoAccessException;
}
// **************************************************
try
{
this.currentThreadUser = System.Threading.Thread.CurrentPrincipal.Identity.Name;
}
catch (System.Security.SecurityException)
{
this.currentThreadUser = this.errorPermissionDenied;
}
catch
{
this.currentThreadUser = this.errorInfoAccessException;
}
// **************************************************
try
{
this.machineName = System.Environment.MachineName;
}
catch (System.Security.SecurityException)
{
this.machineName = this.errorPermissionDenied;
}
catch
{
this.machineName = this.errorInfoAccessException;
}
// **************************************************
try
{
this.windowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
}
catch (System.Security.SecurityException)
{
this.windowsIdentity = this.errorPermissionDenied;
}
catch
{
this.windowsIdentity = this.errorInfoAccessException;
}
}
private void DoLogging(string message)
{
// Placeholder for future logging
}
#endregion
#region Properties
public System.Collections.Specialized.NameValueCollection AdditionalInformation
{
get
{
return this.additionalInformation;
}
set
{
this.additionalInformation = value;
}
}
public string AppDomainName
{
get
{
return this.appDomainName;
}
}
public string AssemblyName
{
get
{
return this.assemblyName;
}
}
public string CurrentProcessID
{
get
{
return this.currentProcessID;
}
}
public string CurrentThreadID
{
get
{
return this.currentThreadID;
}
}
public string CurrentThreadUser
{
get
{
return this.currentThreadUser;
}
}
public DateTime DateTime
{
get
{
return this.dateTimeUTC.ToLocalTime();
}
}
public string MachineName
{
get
{
return this.machineName;
}
}
public string WindowsIdentityName
{
get
{
return this.windowsIdentity;
}
}
#endregion
}
}