CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Steve Hebert's Development Blog

Steve's Blog - From .Net to dotMath and everything in between.

remote event log reading - code for a command line utility

Here's the code for a command-line utility I've written for gathering EventLog information from remote testing/production machines on our network.  I've found the utility to be pretty handy and can be xcopy'd without any other assemblies.  While the utility writes all information out to the Console, it is 'comma-delimeter safe' so you can redirect the output to a file and open it in excel.

I know I could install bits to read the logs over RSS, but in a large company with oversight on the servers getting these types of tools installed is a pain.  This tool also allows me to parameterize the time range - and since we're reviewing these at regular intervals it makes reading far easier. Every solution has its place - this may work well for others.

If you want to use the code below, just create a command line c# application and paste the two classes into the project.  The first class - EventLogReader - implements main(args) and does some simple house-cleaning.  The second class - EventScanner - does the actual work of deciding which messages to write.  While I haven't had a need to parameterize the EventType, this would be a nice addition.  If you make any mods, I only ask that you let me know so I can link to your work.

The syntax for the program is:  EventLogReader logName timeWindow [machineName]

If you want to grab the last 24 hours of log errors from your application log, use...
   EventLogReader "Application Log" 24

If you want to grab the last 24 of application log entries from a remote machine, use...
   EventLogReader "Application Log" 24 Mongo

Disclaimer:  The code listed below is offered without any warranty expressed or implied.  This is despite anything stated before, after or during this posting.  If you use the code and it causes you any problems, you assume full responsibility for the problems and obsolve the author of any form of responsibility.

I should have been a lawyer...  now, onto the code.

class EventLogReader

{

      /// <summary>

      /// The main entry point for the application.

      /// </summary>

      [STAThread]

      static void Main(string[] args)

      {

      if( args != null )

      {

         if( args.Length < 2 || args.Length >3 )

         {

            Console.WriteLine( WriteParmUsageMessage( "Invalid parameter list" ));

            return;

         }

         string machineName = string.Empty;

         string logName = args[0];

         string stimeWindow = args[1];

 

 

         if( args.Length > 2 )

            machineName = args[2];

 

 

         double timeWindow = 0;

 

         try

         {

 

            timeWindow = Convert.ToDouble(stimeWindow);

            if( timeWindow < 0 )

            {

               Console.WriteLine( WriteParmUsageMessage( "Invalid time window parameter - must be a positive integer value"));

               return;

            }

         }

         catch( Exception  )

         {

            Console.WriteLine( WriteParmUsageMessage( "Invalid time window parameter - must be a positive integer value"));

            return;

         }

 

 

         EventScanner es = new EventScanner();

 

         try

         {

            es.WriteEventLog( logName, machineName, timeWindow );

         }

         catch( Exception e )

         {

            WriteParmUsageMessage(string.Format("Unhandled exception while communicating with the event log:\n{0}", e.Message ));

            return;

         }

      }

      }

 

   static private string WriteParmUsageMessage( string message )

   {

      return string.Format("EventLogReader Error\n{0}:\n    EventLogReader logName timeWindow [machineName]", message );

   }

}

 

 

 

public class EventScanner

{

   private DateTime _cutoffDate = DateTime.MinValue;

 

   // CreateCutoff( hours ) : this function substracts the number of hours from the current

   //   time to create a time window for reported log entries

   private void CreateCutoff( double hours )

   {

      _cutoffDate = DateTime.Now.AddHours( hours * -1);

 

      Console.WriteLine( "Event Log Snapshot from {0} {1} through {2} {3}", _cutoffDate.ToShortDateString(), _cutoffDate.ToShortTimeString(), DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString());

   }

 

 

   // CreateEventLogReader( logName, machineName ) : This function creates an eventlog

   //    object for the associated log name and machine name (if passed).

   public EventLog CreateEventLogReader( string logName, string machineName )

   {

      EventLog log = null;

 

      if( machineName.Length > 0 )

         log = new EventLog(logName, machineName );

      else

         log = new EventLog(logName);

 

      return log;

   }

 

 

   // WriteEventLog() : This function takes the log name and attaches to it

   public void WriteEventLog(string logName, string machineName, double hours)

   {

      // first, we'll open the log

      using( EventLog log = CreateEventLogReader( logName, machineName ))

      {

         // next we'll create our timespan of interest (hours subtracted from current time)

         CreateCutoff(hours);

 

         // finally, we'll scan the log for entries we're looking for.

         // NOTE: here is where you can change the entry type based on what you are seeking

         foreach( EventLogEntry entry in log.Entries )

         {

            if(  entry.TimeWritten >= _cutoffDate && entry.EntryType == EventLogEntryType.Error)

               Console.WriteLine( string.Format("{0},{1} {2},{3}", entry.Source, entry.TimeWritten.ToShortDateString(), entry.TimeWritten.ToShortTimeString(), FormatMessage(entry.Message)  ));

 

            entry.Dispose();

         }

      }

   }

 

   // the following string fragment appears on each log entry - apparently due to a

   // translation dll not being loaded.

   private const string _messageFormatIndicator = "following replacement strings:";

 

   private string FormatMessage(string entry)

   {

      string newEntry = entry;

 

      // make certain the generic handler error is ignored

      int truncPosition = entry.IndexOf( _messageFormatIndicator ) ;

 

      if( truncPosition >= 0 )

      {

         truncPosition += _messageFormatIndicator.Length;

         newEntry = entry.Substring( truncPosition, entry.Length - truncPosition );

      }

 

      // get rid of CR/LF combinations for easier reading

      newEntry = newEntry.Replace("\n", "{LF}");

      newEntry = newEntry.Replace("\r", "{CR}");

 

      // get rid of embedded commas to prevent CSV parsing problems

      newEntry = newEntry.Replace(",", "_");

 

      return newEntry;

   }

}

 

 



Check out Devlicio.us!

Our Sponsors