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

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

  • Comments 2
  • Likes
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.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • I know this is old, but is this reliable?  I have heard that the Windows Event Log is a circular buffer, in that when the log is full, it will start dropping old logs to put in new ones.  

    Does that mean that NumberOfRecords will not actually be returning the top recordnumber, and instead be returning the actual number of logs in the Event Log?

  • What's the 2008R2 equivalent for this?

    Set colLoggedEvents = objWMIService.ExecQuery _

       ("Select * From Win32_NTLogEvent Where Logfile = 'Application' AND " & _

           "RecordNumber = " & intRecords)

    ...returns 0 records