Click here to Skip to main content
15,888,610 members
Articles / Web Development / ASP.NET

Zeta Enterprise Library

Rate me:
Please Sign up or sign in to vote.
4.97/5 (14 votes)
16 Jan 2010CPOL3 min read 50.3K   2.3K   48  
A small set of general-purpose classes for using in .NET applications (2.0 or higher)
namespace Zeta.EnterpriseLibrary.Logging
{
	#region Using directives.
	// ----------------------------------------------------------------------

	using System;
	using System.Globalization;
	using System.Net;
	using System.IO;
	using System.Net.NetworkInformation;
	using System.Reflection;
	using System.Collections.Generic;
	using System.Net.Sockets;
	using System.Diagnostics;
	using System.Text;

	// ----------------------------------------------------------------------
	#endregion

	/////////////////////////////////////////////////////////////////////////

	/// <summary>
	/// Independently usable class that returns various strings with
	/// environment-related logging information.
	/// </summary>
	public class LoggingInformation
	{
		#region Static member.
		// ------------------------------------------------------------------

		/// <summary>
		/// Return a string with a collection of all the discrete information
		/// that this class provides.
		/// </summary>
		/// <value>All.</value>
		public static string All
		{
			get
			{
				try
				{
					var additionalInfo = new StringBuilder();

					if ( _needMoreInfoEventHandlers != null )
					{
						foreach (
							EventHandler<LoggingInformationNeedMoreInfoEventArgs> handler
								in _needMoreInfoEventHandlers )
						{
							var args =
								new LoggingInformationNeedMoreInfoEventArgs();

							// Call handler.
							Debug.Assert( handler != null );
							handler( null, args );

							if ( !string.IsNullOrEmpty( args.MoreInformation ) )
							{
								// Add information.
								additionalInfo.AppendLine( args.MoreInformation );
								additionalInfo.AppendLine();
							}
						}
					}

					var info = new StringBuilder();

					info.Append( additionalInfo.ToString().Trim() );
					additionalInfo.AppendLine();
					additionalInfo.AppendLine();

					additionalInfo.AppendLine( WindowsEnvironment );
					additionalInfo.AppendLine();
					additionalInfo.AppendLine();

					additionalInfo.AppendLine( NetworkEnvironment );
					additionalInfo.AppendLine();
					additionalInfo.AppendLine();

					additionalInfo.AppendLine( Assemblies );

					return info.ToString().Trim();
				}
				catch ( Exception x )
				{
					// As suggested, do catch it here, since it can be
					// security issues that prevent gathering the required
					// information.

					return string.Format(
						@"Exception '{0}' ({1}) inside '{2}'. Stack trace follows: {3}",
						x.Message,
						x.GetType(),
						@"Zeta.EnterpriseLibrary.Logging.LoggingInformation.All",
						x.StackTrace );
				}
			}
		}

		/// <summary>
		/// Occurs when [need more info].
		/// </summary>
		public static event EventHandler<LoggingInformationNeedMoreInfoEventArgs>
			NeedMoreInfo
		{
			add
			{
				Debug.Assert( value != null );

				lock ( _typeLock )
				{
					if ( _needMoreInfoEventHandlers == null )
					{
						_needMoreInfoEventHandlers =
							new List<EventHandler<LoggingInformationNeedMoreInfoEventArgs>>();
					}

					Debug.Assert( !_needMoreInfoEventHandlers.Contains( value ) );
					_needMoreInfoEventHandlers.Add( value );
				}
			}
			remove
			{
				lock ( _typeLock )
				{
					Debug.Assert( _needMoreInfoEventHandlers != null );
					Debug.Assert( _needMoreInfoEventHandlers.Contains( value ) );

					_needMoreInfoEventHandlers.Remove( value );
				}
			}
		}

		/// <summary>
		/// Provide Windows-environment information.
		/// </summary>
		/// <value>The windows environment.</value>
		public static string WindowsEnvironment
		{
			get
			{
				try
				{
					string info =
						string.Format(
							CultureInfo.CurrentCulture,
							@"User domain name: {0}," + Environment.NewLine +
								@"User name: {1}," + Environment.NewLine +
									@"Machine name: {2}," + Environment.NewLine +
										@"OS version: {3}," + Environment.NewLine +
											@"CLR version: {4}," + Environment.NewLine +
												@"Command line: {5}," + Environment.NewLine +
													@"Current directory: {6}.",
							Environment.UserDomainName ?? @"(null)",
							Environment.UserName,
							Environment.MachineName,
							Environment.OSVersion == null ? @"(null)" : Environment.OSVersion.ToString(),
							Environment.Version,
							Environment.CommandLine ?? @"(null)",
							Environment.CurrentDirectory );

					return info;
				}
				catch ( Exception x )
				{
					// As suggested, do catch it here, since it can be
					// security issues that prevent gathering the required
					// information.

					return string.Format(
						@"Exception '{0}' ({1}) inside '{2}'.",
						x.Message,
						x.GetType(),
						@"Zeta.EnterpriseLibrary.Logging.LoggingInformation.WindowsEnvironment" );
				}
			}
		}

		/// <summary>
		/// Get the DNS name of the host.
		/// </summary>
		/// <param name="hostName">Name of the host.</param>
		/// <returns></returns>
		public static string DnsGetHostEntryName(
			string hostName )
		{
			if ( string.IsNullOrEmpty( hostName ) )
			{
				return string.Empty;
			}
			else
			{
				try
				{
					var iphe = Dns.GetHostEntry( hostName );
					return iphe.HostName;
				}
				catch ( SocketException )
				{
					return string.Empty;
				}
			}
		}

		/// <summary>
		/// Provide network-environment information.
		/// </summary>
		/// <value>The network environment.</value>
		public static string NetworkEnvironment
		{
			get
			{
				try
				{
					var hostName = Dns.GetHostName();

					var infos = new StringBuilder();
					infos.AppendFormat(
						CultureInfo.CurrentCulture,
						@"Host name: {0}",
						hostName ?? @"(null)" );

					foreach ( var i in NetworkInterface.GetAllNetworkInterfaces() )
					{
						foreach ( var iAddress in i.GetIPProperties().UnicastAddresses )
						{
							var ipa = iAddress.Address.ToString();

							infos.AppendFormat(
								CultureInfo.CurrentCulture,
								@",{0}IP address: {1}{0}Lookup address: http://zeta-sw.com/geoip.aspx?ip={1}",
								Environment.NewLine,
								ipa ?? @"(null)" );
						}
					}

					return infos.ToString().TrimEnd().TrimEnd( ',', '.' ).TrimEnd() + @".";
				}
				catch ( Exception x )
				{
					// As suggested, do catch it here, since it can be
					// security issues that prevent gathering the required
					// information.

					return string.Format(
						@"Exception '{0}' ({1}) inside '{2}'.",
						x.Message,
						x.GetType(),
						@"Zeta.EnterpriseLibrary.Logging.LoggingInformation.NetworkEnvironment" );
				}
			}
		}

		/// <summary>
		/// Provide information about the current assemblies.
		/// </summary>
		/// <value>The assemblies.</value>
		public static string Assemblies
		{
			get
			{
				var assemblies =
					new List<AssemblyInfo>
						{
							new AssemblyInfo(@"Entry assembly", Assembly.GetEntryAssembly()),
							new AssemblyInfo(@"Executing assembly", Assembly.GetExecutingAssembly()),
							new AssemblyInfo(@"Calling assembly", Assembly.GetCallingAssembly())
						};

				// Add all loaded assemblies.
				// (This is redundant with the above but still OK).
				var asms = AppDomain.CurrentDomain.GetAssemblies();
				if ( asms != null )
				{
					int index = 0;
					foreach ( var asm in asms )
					{
						assemblies.Add(
							new AssemblyInfo(
								string.Format(
									@"Domain assembly {0}/{1}.",
									index + 1,
									asms.Length ),
								asm ) );

						index++;
					}
				}

				// --

				var infos = string.Empty;

				var loopCount = 0;
				foreach ( var pair in assemblies )
				{
					var assemblyType = pair.Name;
					var assembly = pair.Assembly;

					if ( assembly != null )
					{
						string info = string.Format(
							CultureInfo.CurrentCulture,
							@"Assembly type: {0}," + Environment.NewLine +
								@"Assembly full name: {1}," + Environment.NewLine +
									@"Assembly location: {2}," + Environment.NewLine +
										@"Assembly date: {3}," + Environment.NewLine +
											@"Assembly version: {4}."
							,
							assemblyType,
							assembly.FullName ?? @"(null)",
							getAssemblyLocation( assembly ) ?? @"(null)",
							getAssemblyLocation( assembly ) == null
								? @"(null)"
								: getLastFileWriteTime( getAssemblyLocation( assembly ) ).ToString( CultureInfo.CurrentCulture ),
							assembly.GetName().Version == null
								? @"(null)"
								: assembly.GetName().Version.ToString() );

						if ( loopCount > 0 )
						{
							infos += Environment.NewLine + Environment.NewLine;
						}

						infos += info;
					}

					loopCount++;
				}

				return infos;
			}
		}

		/// <summary>
		/// Gets the last file write time.
		/// </summary>
		/// <param name="filePath">The file path.</param>
		/// <returns></returns>
		private static DateTime getLastFileWriteTime(
			string filePath )
		{
			if ( string.IsNullOrEmpty( filePath ) )
			{
				return DateTime.MinValue;
			}
			else if ( !File.Exists( filePath ) )
			{
				return DateTime.MinValue;
			}
			else
			{
				return File.GetLastWriteTime( filePath );
			}
		}

		/// <summary>
		/// Dynamic assemblies don't support the location.
		/// </summary>
		/// <param name="assembly">The assembly.</param>
		/// <returns></returns>
		private static string getAssemblyLocation(
			Assembly assembly )
		{
			try
			{
				return assembly.Location;
			}
			catch ( NotSupportedException )
			{
				return null;
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Helper class for iterating.
		// ------------------------------------------------------------------

		/// <summary>
		/// Helper class for iterating.
		/// </summary>
		private class AssemblyInfo
		{
			#region Public methods.

			/// <summary>
			/// Initializes a new instance of the <see cref="AssemblyInfo"/> 
			/// class.
			/// </summary>
			/// <param name="name">The name.</param>
			/// <param name="assembly">The assembly.</param>
			public AssemblyInfo(
				string name,
				Assembly assembly )
			{
				_name = name;
				_assembly = assembly;
			}

			#endregion

			#region Public properties.

			/// <summary>
			/// Gets the name.
			/// </summary>
			/// <value>The name.</value>
			public string Name
			{
				get
				{
					return _name;
				}
			}

			/// <summary>
			/// Gets the assembly.
			/// </summary>
			/// <value>The assembly.</value>
			public Assembly Assembly
			{
				get
				{
					return _assembly;
				}
			}

			#endregion

			#region Private variables.

			private readonly string _name;
			private readonly Assembly _assembly;

			#endregion
		}

		// ------------------------------------------------------------------
		#endregion

		#region Private helper.
		// ------------------------------------------------------------------

		private static readonly object _typeLock = new object();

		private static List<EventHandler<LoggingInformationNeedMoreInfoEventArgs>>
			_needMoreInfoEventHandlers;

		// ------------------------------------------------------------------
		#endregion
	}

	/////////////////////////////////////////////////////////////////////////
}

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer Zeta Software GmbH
Germany Germany
Uwe does programming since 1989 with experiences in Assembler, C++, MFC and lots of web- and database stuff and now uses ASP.NET and C# extensively, too. He has also teached programming to students at the local university.

➡️ Give me a tip 🙂

In his free time, he does climbing, running and mountain biking. In 2012 he became a father of a cute boy and in 2014 of an awesome girl.

Some cool, free software from us:

Windows 10 Ereignisanzeige  
German Developer Community  
Free Test Management Software - Intuitive, competitive, Test Plans.  
Homepage erstellen - Intuitive, very easy to use.  
Offline-Homepage-Baukasten

Comments and Discussions