Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Archives
Subscribe
December 9, 2025

More Eventlog Eventing

In this issue:

  • Operational and Admin Logs
  • EventLogWatcher
    • Creating a Watcher
    • Registering an Event Subscriber
    • Processing an Event
    • Retrieving Event Data
    • Filtering
    • Filtering on Event Type
  • Remote Event Queries
  • Summary

Last time we started looking at creating event subscribers for new event log entries. This is a handy technique when you want to monitor specific events but there isn't a direct event that you can subscribe to. If the thing you are interested in writes an event log entry, you can create an event subscriber for that.

The first step is to identify the event log you need to monitor This is because the type of event log will dictate how you subscribe to it. In the previous article, we looked at the classic event logs like System and Application. These are the types of event logs that have been around since the days of Windows NT. However, they also include newer logs like Windows PowerShell.

Windows Vista introduced a new event log format and many new logs that we refer to as operational or admin logs.

Operational and Admin Logs

Before you can create an event subscription, you need to identify the event log you want to monitor.The best way is to use Get-WinEvent. You can run this command to list all event logs.

Get-WinEvent -ListLog *

Note that this will also include classic event logs. But they are easy to filter out.

PS C:\>  Get-WinEvent -ListLog * | Where {-Not $_.IsClassicLog -AND $_.RecordCount -gt 0 }

LogMode   MaximumSizeInBytes RecordCount LogName
-------   ------------------ ----------- -------
Circular             1052672        2428 Setup
Circular            15728640        1116 PowerShellCore/Operational
Circular             1052672          27 OpenSSH/Operational
Circular             1052672        1115 Microsoft-Windows-WMI-Activity/Operational
Circular             1052672        1423 Microsoft-Windows-WLAN-AutoConfig/Operational
...

EventLogWatcher

To monitor these type of event logs, you will need to use a special .NET class, the System.Diagnostics.Eventing.Reader.EventLogWatcher. I can discover a bit more by using the Get-TypeMember command from the PSScriptTools module.

PS C:\> Get-TypeMember System.Diagnostics.Eventing.Reader.EventLogWatcher

   Type: System.Diagnostics.Eventing.Reader.EventLogWatcher

Name               MemberType ResultType IsStatic IsEnum
----               ---------- ---------- -------- ------
EventRecordWritten Event
GetType            Method     Type
Enabled            Property   Boolean

I can also check the constructor, or how to create a new instance.

PS C:\> Get-TypeConstructor System.Diagnostics.Eventing.Reader.EventLogWatcher

[System.Diagnostics.Eventing.Reader.EventLogWatcher]::new([System.String]$Path))

[System.Diagnostics.Eventing.Reader.EventLogWatcher]::new([System.Diagnostics.Eventing.Reader.EventLogQuery]$eventQuery))

[System.Diagnostics.Eventing.Reader.EventLogWatcher]::new([System.Diagnostics.Eventing.Reader.EventLogQuery]$eventQuery),[System.Diagnostics.Eventing.Reader.EventBookmark]$Bookmark))

[System.Diagnostics.Eventing.Reader.EventLogWatcher]::new([System.Diagnostics.Eventing.Reader.EventLogQuery]$eventQuery),[System.Diagnostics.Eventing.Reader.EventBookmark]$Bookmark),[System.Boolean]$readExistingEvents))

> Get-TypeConstructor is also part of PSScriptTools.

Creating a Watcher

Let's create a simple watcher for the Windows Remote Management log.

PS C:\> $elw = [System.Diagnostics.Eventing.Reader.EventLogWatcher]::new("Microsoft-Windows-WinRM/Operational")
PS C:\> $elw |

Enabled
-------
  False

The event log watcher has a single property. Before I can use it, I need to enable it.

$elw.Enabled = $true

Registering an Event Subscriber

To use the watcher, you will need to use the Register-ObjectEvent cmdlet. In order to use the watcher on an object, in this case $elw, you need to subscribe to a specific event. If you look back at the output of Get-TypeMember, you can see that the event is called EventRecordWritten.

The other properties are similar to other event subscribers you have created in the past.

Register-ObjectEvent -InputObject $elw -EventName "EventRecordWritten" -MessageData "Something happened!" -SourceIdentifier "WatchWSMan"

There isn't any polling like we had with WMI/CIM event subscribers. I also am watching for any event in the log. I'll cover filtering later.

Processing an Event

Eventually, I'll get an event.

PS C:\> Get-Event -id 1

ComputerName     :
RunspaceId       : e3b1a2ab-a387-4c51-91f9-2efff8b71516
EventIdentifier  : 1
Sender           : System.Diagnostics.Eventing.Reader.EventLogWatcher
SourceEventArgs  : System.Diagnostics.Eventing.Reader.EventRecordWrittenEventArgs
SourceArgs       : {System.Diagnostics.Eventing.Reader.EventLogWatcher, System.Diagnostics.Eventing.Reader.EventRecordWrittenEventArgs}
SourceIdentifier : WatchWSMan
TimeGenerated    : 12/8/2025 4:11:47 PM
MessageData      : Something happened!

As with previous event subscribers, I can use the SourceEventArgs property to get more information about the event.

PS C:\> (Get-Event -id 1).SourceEventArgs

EventRecord                                       EventException
-----------                                       --------------
System.Diagnostics.Eventing.Reader.EventLogRecord

PS C:\> (Get-Event -id 1).SourceEventArgs.EventRecord

   ProviderName: Microsoft-Windows-WinRM

TimeCreated                     Id LevelDisplayName Message
-----------                     -- ---------------- -------
12/8/2025 4:11:47 PM            91 Information

Never assume this is all there is.

PS C:\> (Get-Event -id 1).SourceEventArgs.EventRecord | Select-Object *

Id                   : 91
Version              : 0
Qualifiers           :
Level                : 4
Task                 : 9
Opcode               : 0
Keywords             : 4611686018427387908
RecordId             : 321427
ProviderName         : Microsoft-Windows-WinRM
ProviderId           : a7975c8f-ac13-49f1-87da-5a984a4ab417
LogName              : Microsoft-Windows-WinRM/Operational
ProcessId            : 17256
ThreadId             : 35408
MachineName          : Prospero
UserId               : S-1-5-21-3465062479-264850141-705915528-1001
TimeCreated          : 12/8/2025 4:11:47 PM
ActivityId           : 0f0b7f5d-67b9-0006-9edc-110fb967dc01
RelatedActivityId    :
ContainerLog         : Microsoft-Windows-WinRM/Operational
MatchedQueryIds      : {}
Bookmark             : System.Diagnostics.Eventing.Reader.EventBookmark
LevelDisplayName     : Information
OpcodeDisplayName    : Info
TaskDisplayName      : Request handling
KeywordsDisplayNames : {Server}
Properties           : {System.Diagnostics.Eventing.Reader.EventProperty}

Retrieving Event Data

Depending on the log, you might see different information. In this case, what I don't see is the message text. One way around that is to use the event recored's FormatDescription() method.

PS C:\> $r = (Get-Event -id 1).SourceEventArgs.EventRecord
PS C:\> $r.FormatDescription()
Creating WSMan shell on server with ResourceUri: http://schemas.microsoft.com/powershell/Microsoft.PowerShell (PROSPERO\jeff clientIP: fe80::eef9:5d0d:89a8:d794%20)

With this information, I can process all the events.

PS C:\> Get-Event | Sort TimeGenerated | Select TimeGenerated,EventIdentifier,
@{Name="EventID";Expression = {$_.SourceEventArgs.EventRecord.ID}},
@{Name="Operation";Expression = {$_.SourceEventArgs.EventRecord.OpcodeDisplayName}},
@{Name="Task";Expression = {$_.SourceEventArgs.EventRecord.TaskDisplayName}},
@{Name="Message";Expression = {$_.SourceEventArgs.EventRecord.FormatDescription()}},
@{Name="Computername"; Expression = {$_.SourceEventArgs.EventRecord.MachineName.ToUpper()} }

TimeGenerated   : 12/8/2025 4:11:47 PM
EventIdentifier : 1
EventID         : 91
Operation       : Info
Task            : Request handling
Message         : Creating WSMan shell on server with ResourceUri: http://schemas.microsoft.com/
                  powershell/Microsoft.PowerShell  (PROSPERO\jeff clientIP: fe80::eef9:5d0d:89a8:d794%20)
Computername    : PROSPERO

TimeGenerated   : 12/8/2025 4:41:27 PM
EventIdentifier : 2
EventID         : 145
Operation       : Info
Task            : Request handling
Message         : WSMan operation Enumeration started with resourceUri http://schemas.microsoft.com/
                  wbem/wsman/1/config/listener
Computername    : PROSPERO
...
Want to read the full issue?
GitHub
Bluesky
LinkedIn
https://techhub...
https://jdhitso...
Powered by Buttondown, the easiest way to start and grow your newsletter.