Event Log Parsing for the WSH Administrator

In the first two segments of this series we explored ways of analyzing and archiving event logs with WSH. In this article, I’m going to demonstrate specific applications of this that can benefit network administrators who are responsible for maintaining large numbers of machines.

Contributed by
Rating: 5 stars5 stars5 stars5 stars5 stars / 4
May 23, 2007
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

This scripts we’ll be creating in this article will take a two-fold approach.  The first is designed to be run from a server to consolidate event logs from several machines.  The second is designed as a network logon script that can be deployed on each machine in the network.

The two-fold approach has two major benefits.  The first script can be managed from a single location.  It doesn’t require installation on every machine, which means it can be run at will as needed.

The second script is designed to be run from each machine.  This gives us the advantage of creating a real time monitor that can be used for instant notification when specific conditions occur.

You can use these methods independently of one another or in conjunction to obtain the desired level of efficiency that you are seeking.  I’ll discuss this further as I show you specific case scenarios.

You’re going to need the script that we ended with in the last article.  We’re going to further modify it for our needs.  Both of the scripts that will be introduced in this article will grow off of the examples you’ve already seen.

I’m not going to be showing you how to sort and manage the data that we retrieve from the event logs.  I may write an article later for that purpose, but for now, my goal is simply to show you how to prepare the data.

I’m going to be making two assumptions throughout this article.  I believe they represent the most common opinions of network administrators as a whole.  You can, however, modify any of these to fit your own specific needs.

The first assumption is that all event log entries should be archived.  For the sake of size and time you may wish to limit this to only certain types of events, but I believe that most administrators will agree that historical data is best preserved in its entirety.

The second assumption is that you do not need to know about every single event that takes place in a system—especially when you are managing large numbers of systems.  Whenever monitoring or creating notifications, I will be limiting the range of data that we are watching.

Again, any of these options can be modified to fit your own specific needs and style.

One third and final thing to note is that I will be archiving all data in one central database.  Since each event is labeled by a machine name, sorting data for specific machines is not impossible.  You could easily create multiple databases for individual machines or groups of machines if you preferred.

Modularizing the script

Let’s being by creating a script that will pull the event logs from machines across your network.  I suggest creating a static list of machines to interrogate.  While you could create a script that will seek other machines, the first is much more reliable and much easier to manage in the event that errors occur.

You can pull machine names from a database or flat file, but for the sake of brevity, I’m just going to create an array to hold them.  Again, this can be changed based on your own needs and ease of use.

To make things easier as we progress, let’s take the time now to separate our script into sections.  This way we can modify it more easily as we go.

strConnection = "Provider=Microsoft.Jet.OLEDB.4.0; " _

   & "Data Source=C:events.mdb"

 

arrComputers = Array("machine1", _

   "machine2", _

   "machine3")

 

Set objFso = CreateObject("Scripting.FileSystemObject")

 

If objFso.FileExists("C:events.mdb") Then

   oConn.Open strConnection

Else

   BuildDatabase

End If

 

Set objWMIService = GetObject("winmgmts:" _

   & "{impersonationLevel=impersonate}!" & strComputer _

   & "rootcimv2")

The opening segment assigns some variables and connects to the WMI Service.  I’ve also included an If statement that checks to see whether the database needs to be created first.

Sub BuildDatabase

   Set objCatalog = CreateObject("ADOX.Catalog")

   objCatalog.Create strConnection

   Set objCatalog = Nothing

   Set oConn = CreateObject("ADODB.Connection")

   oConn.Open strConnection

   oConn.Execute "CREATE TABLE EventTable(" _

      & "Category INT, " _

      & "ComputerName VARCHAR(50), " _

      & "EventCode INT, " _

      & "Message VARCHAR(100), " _

      & "EventType VARCHAR(50), " _

      & "RecordNumber INT, " _

      & "SourceName VARCHAR(50), " _

      & "TypeDesc VARCHAR(15), " _

      & "UserName VARCHAR(50), " _

      & "TimeGenerated VARCHAR(19), " _

      & "TimeWritten VARCHAR(19)" _

      & ")", , 129

End Sub

The next section is used to create a database.  I’ve moved this into an appropriately named subroutine.

Sub GetEvents

   Set colEvents = objWMIService.ExecQuery( _

      "SELECT * FROM Win32_NTLogEvent")

 

   Set objRs = CreateObject("ADODB.Recordset")

   objRs.Open "SELECT * FROM EventTable;", oConn, 0, 3

 

   For Each objEvent In colEvents

       objRs.AddNew

       objRs("Category") = objEvent.Category

       objRs("ComputerName") = objEvent.ComputerName

       objRs("EventCode") = objEvent.EventCode

       strMessage = objEvent.Message

       If Len(strMessage) > 100 Then

          strMessage = Left(strMessage, 100)

       End If

       objRs("Message") = strMessage

       objRs("EventType") = objEvent.EventType

       objRs("RecordNumber") = objEvent.RecordNumber

       objRs("SourceName") = objEvent.SourceName

       objRs("TypeDesc") = objEvent.Type

       strUser = objEvent.User

       If IsNull(strUser) Then strUser = "N/A"

       objRs("UserName") = strUser

       objRs("TimeGenerated") = Date2String(objEvent.TimeGenerated)

       objRs("TimeWritten") = Date2String(objEvent.TimeWritten)

       objRs.Update

       objEvent.ClearEventLog()

   Next

   objRs.Close

End Sub

In this section we query WMI for events and add them to our database.  Again, I’ve moved this into a subroutine.  I’ve also added a line to clear the event log on the machine after archiving it.  This prevents archiving the same event each time the script is run.

Polling machines across a network

Since WMI supports working with remote computers, we just need to change our script so that it polls each computer in our array in turn.  To do this, we’ll need to recreate the WMI service object for each machine.  We’ll begin by creating a For loop to move through the array.

strConnection = "Provider=Microsoft.Jet.OLEDB.4.0; " _

   & "Data Source=C:events.mdb"

 

arrComputers = Array("machine1", _

   "machine2", _

   "machine3")

 

If objFso.FileExists("C:events.mdb") Then

   oConn.Open strConnection

Else

   BuildDatabase

End If

 

For i = 0 To UBound(arrComputers)

   strComputer = arrComputers(i)

   Set objWMIService = GetObject("winmgmts:" _

       & "{impersonationLevel=impersonate}!" & strComputer _

       & "rootcimv2")

   GetEvents

   Set objWMIService = Nothing

Next

 

oConn.Close

This simply moves through each computer name in our array, connects to the WMI Service, and then calls the GetEvents subroutine to retrieve the events on that machine.

Function Date2String(objTime)

    yyyy = Left(objTime, 4)

    mm = Mid(objTime, 5, 2)

    dd = Mid(objTime, 7, 2)

    hh = Mid(objTime, 9, 2)

    min = Mid(objTime, 11, 2)

    sec = Mid(objTime, 13, 2)

    Date2String = mm & "/" & dd & "/" & yyyy & " " & hh & ":" & min & ":" & sec

End Function

Don’t forget to add all required subroutines to your completed script.

Monitoring event logs

Let’s take a look at how to create a logon script that monitors the event logs.  We’re going to add an extra feature to have the script send an email notification if it detects a warning or error event.

strComputer = "."

 

Set objWMIService = GetObject("winmgmts:{(Security)}" & strComputer _

   & "rootcimv2")

Set colEvents = objWMIService.ExecNotificationQuery _

   ("SELECT * FROM __InstanceCreationEvent WHERE " _

       & "TargetInstance ISA 'Win32_NTLogEvent' " _

       & "AND TargetInstance.Type = 'Warning' " _

       & "OR TargetInstance.Type = 'Error'")

Do While True

   Set objEvent = colEvents.NextEvent()

   strUser = objEvent.User

   If IsNull(strUser) Then strUser = "N/A"

   strMessage = objEvent.Message

   If Len(strMessage) > 100 Then

       strMessage = Left(strMessage, 100)

   End If

 

   return = EmailNotify(objEvent.Category, _

       objEvent.ComputerName, _

       objEvent.EventCode, _

       strMessage, _

       objEvent.EventType, _

       objEvent.RecordNumber, _

       objEvent.SourceName, _

       objEvent.Type, _

       strUser, _

       DateTime2String(objEvent.TimeGenerated), _

       DateTime2String(objEvent.TimeWritten))

Loop

The base script looks like this.  It connects to the WMI Service and issues an Event Notification Query.  This script utilizes event scripting.  That means our script will only be executed when a new event occurs that matches our parameters.  This script will run indefinitely any time the computer is turned on.

If the event is a Warning or Error type event, the event’s details are passed to the EmailNotify function.

Function EmailNotify(intCategory, strComputerName, intEventCode, strMessage, strEventType, intRecordNumber, strSourceName, strTypeDesc, strUserName, strTimeGenerated, strTimeWritten)

   strBody = "Category: " & CStr(intCategory) & VbCrLf

   strBody = strBody & "ComputerName: " & strComputerName & VbCrLf

   strBody = strBody & "EventCode: " & CStr(intEventCode) & VbCrLf

   strBody = strBody & "Message: " & strMessage & VbCrLf

   strBody = strBody & "EventType: " & strEventType & VbCrLf

   strBody = strBody & "RecordNumber: " & CStr(intRecordNumber) & VbCrLf

   strBody = strBody & "SourceName: " & strSourceName & VbCrLf

   strBody = strBody & "TypeDesc: " & strTypeDesc & VbCrLf

   strBody = strBody & "User: " & strUserName & VbCrLf

   strBody = strBody & "TimeGenerated: " & strTimeGenerated & VbCrLf

   strBody = strBody & "TimeWritten: " & strTimeWritten & VbCrLf

 

   Set objEmail = CreateObject("CDO.Message")

   objEmail.From = "Notify Script"

   objEmail.To = "admin@mymail.com"

   objEmail.Subject = "New Event Notification"

   objEmail.Textbody = strBody

   objEmail.Configuration.Fields.Item _

   ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2

   objEmail.Configuration.Fields.Item _

   ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = _

       "smtp.mymail.com"

   objEmail.Configuration.Fields.Item _

   ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25

   objEmail.Configuration.Fields.Update

   objEmail.Send

   Set objEmail = Nothing

   EmailNotify = 1

End Function

This function assembles the event details into an email message that is sent to an administrator using CDO.  Be sure to change both the destination address and the SMTP server to match your configuration.

Function Date2String(objTime)

    yyyy = Left(objTime, 4)

    mm = Mid(objTime, 5, 2)

    dd = Mid(objTime, 7, 2)

    hh = Mid(objTime, 9, 2)

    min = Mid(objTime, 11, 2)

    sec = Mid(objTime, 13, 2)

    Date2String = mm & "/" & dd & "/" & yyyy & " " & hh & ":" & min & ":" & sec

End Function

You’ll also need the Date2String function to create friendly date and time stamps.

There you have it.  Two scripts that a network administrator can use to monitor or track the event logs for machines within their network.  Making use of scripts like this will improve your efficiency and keep you in closer contact with the machines you service.

Good luck maintaining your machines.  Until next time…keep coding!

blog comments powered by Disqus
WINDOWS SCRIPTING ARTICLES

- More Windows Scripting Workarounds from Nilpo
- Overloading Methods and More in VBScript
- Improving MFC for Windows Vista
- Regular Expressions in VBScript
- Working with Dates in WMI
- Completing Calendars with VBScript Date Func...
- Building Calendars with VBScript Date Functi...
- Working With Dates and Times in VBScript
- Designing WCF DataContract Classes Using the...
- Understanding Dates and Times in VBScript
- Working With Arrays in VBScript
- Compressed Folders in WSH
- Using .NET Interops in VBScript
- Nilpo`s Scripting Secrets, Vol I
- Database operations using Silverlight 2.0 WC...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
 
 
 

ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 1 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials