How Can I Return Only the Last Record Written to an Event Log?

Avatar

Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I read only the last record written to an event log? In other words, what is the WMI equivalent to the SQL statement Select Top 1?

— KM

SpacerHey, Scripting Guy! AnswerScript Center

Hey, KM. Well, as it turns out WMI doesn’t have an equivalent to the Select Top command; for better or worse, the WMI Query Language (WQL) has only a small subset of the commands found in SQL. That doesn’t mean we can’t return only the last record written to an event log, it just means we have to be a bit sneaky about it.

To get just the last record we need to do two things. To begin with, we need to figure out how many records are in an event log. That’s important information, because events are numbered sequentially when they are added to an event log; in other words, the first event written to an event log is record 1, the second is record 2, etc. If there are 4,912 events in an event log, then the very last record written to the log has to be record number 4912. After we know the total number of records, we can then write a query that returns only events with a record number equal to the total number of records. That record is the last record written to the log.

Here’s a simple little script that determines the total number of records in the Application event log, and stores that value in the variable intRecords:

strComputer = “.”
Set objWMIService = GetObject(“winmgmts:” _
    & “{impersonationLevel=impersonate}!\\” & strComputer & “\root\cimv2”)

Set objInstalledLogFiles = objWMIService.ExecQuery _ (“Select * from Win32_NTEventLogFile Where LogFileName = ‘Application'”)

For Each objLogfile in objInstalledLogFiles intRecords = objLogFile.NumberOfRecords Next

Now we need a query that returns all events from the Application event log where the RecordNumber is equal to value of intRecords (and there will only be one such record, seeing as how record numbers are unique). Here’s a query that does just that:

Set colLoggedEvents = objWMIService.ExecQuery _
    (“Select * From Win32_NTLogEvent Where Logfile = ‘Application’ AND ” & _
        “RecordNumber = ” & intRecords)

All that’s left now is to put these two script snippets together, and then add a For Each loop in which we echo the properties of this record:

strComputer = “.”
Set objWMIService = GetObject(“winmgmts:” _
    & “{impersonationLevel=impersonate}!\\” & strComputer & “\root\cimv2”)

Set objInstalledLogFiles = objWMIService.ExecQuery _ (“Select * from Win32_NTEventLogFile Where LogFileName = ‘Application'”)

For Each objLogfile in objInstalledLogFiles intRecords = objLogFile.NumberOfRecords Next

Set colLoggedEvents = objWMIService.ExecQuery _ (“Select * From Win32_NTLogEvent Where Logfile = ‘Application’ AND ” & _ “RecordNumber = ” & intRecords)

For Each objEvent in colLoggedEvents Wscript.Echo “Category: ” & objEvent.Category Wscript.Echo “Computer Name: ” & objEvent.ComputerName Wscript.Echo “Event Code: ” & objEvent.EventCode Wscript.Echo “Message: ” & objEvent.Message Wscript.Echo “Record Number: ” & objEvent.RecordNumber Wscript.Echo “Source Name: ” & objEvent.SourceName Wscript.Echo “Time Written: ” & objEvent.TimeWritten Wscript.Echo “Event Type: ” & objEvent.Type Wscript.Echo “User: ” & objEvent.User Next

That should do the trick.

0 comments

Comments are closed.