Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Subscribe
Archives
September 9, 2025

What is Happening?

> What's the buzz? > Tell me what's-a-happening. > -- Jesus Christ Superstar

Managing an IT infrastructure is a complex task that involves coordinating various components, services, and applications. For better or worse are environments are not static, they are constantly changing. I bet a lot of your workday is spent reacting to these changes, especially when something changes for the worse. This is why many organizations invest in monitoring and alerting systems to help them stay on top of their infrastructure's health. However, not every organization has the resources or expertise. Or you might need to monitor changes on a short-term basis to troubleshoot a specific issue. This is where eventing comes in.

Eventing

Eventing is a powerful paradigm that allows you to react to changes in your infrastructure in real-time. When something happen in Windows such as a process starting, a file being modified, or a service stopping, an event is generated. You'll hear this referred to as an event being "fired". Fortunately for us, you can subscribe to these events. What you do when the event is fired is up to you. You can accept a simple notification, or you can trigger a scripted response. Of course, we want to leverage PowerShell to do this.

I want to begin exploring this topic by demonstrating events in WMI. WMI is a dynamic technology that is doing more than you realize. We typically think of querying WMI with Get-CimInstance to discover information based on defined classes like Win32_Process or Win32_Service. However, WMI has an integrated eventing system that you can tap into. When something changes on a computer, there's a good change WMI is aware of it and can notify you. Let me show you how.

Eventing Instances

To track WMI events, you need to understand the concept of eventing instances. These are special classes in WMI that represent different types of events.

PS C:\> Get-CimClass -ClassName __instance*event | Select-Object CimClassname,CimClassProperties

CimClassName                CimClassProperties
------------                ------------------
__InstanceOperationEvent    {SECURITY_DESCRIPTOR, TIME_CREATED, TargetInstance}
__InstanceModificationEvent {SECURITY_DESCRIPTOR, TIME_CREATED, TargetInstance, PreviousInstance}
__InstanceCreationEvent     {SECURITY_DESCRIPTOR, TIME_CREATED, TargetInstance}
__InstanceDeletionEvent     {SECURITY_DESCRIPTOR, TIME_CREATED, TargetInstance}

The double underscore (__) prefix indicates these are system classes. The Instance part of the name indicates these events are related to instances of other classes. The last part of the name indicates the type of event. I'm only going to focus on creating, deletion, and modification events.

You will need to create a query for your event subscription. The query will watch once of the instance class names. However, these are generic classes. You will need to specify what target class you want to monitor. You will need to use the ISA keyword to specify the target class. For example, if you want to monitor when a new process is created, you would use the Win32_Process class as the target class.

$query = "Select * from __InstanceCreationEvent where TargetInstance ISA 'Win32_Process'"

Note that I am quoting the target class name.

Polling

Before we create the event subscription, there is one more key element and that is timing. You can think of the query as a ping. Did an event happen? How about now? Now? This is usually not efficient, especially when monitoring for changes on a remote computer. Instead, the accepted practice is to use polling. Polling is a technique where the system checks for changes at regular intervals. This is done using the WITHIN clause in the query. You specify the interval in seconds. For example, if you want to check for new processes every 5 seconds, you would modify the query like this:

$query = "Select * from __InstanceCreationEvent where TargetInstance ISA 'Win32_Process' WITHIN 5"

You may also see this written like this:

$query = "Select * from __InstanceCreationEvent WITHIN 5 where TargetInstance ISA 'Win32_Process'"

Which may make more logical sense. I never set polling intervals lower than 5 seconds. This is a good balance between responsiveness and resource usage. If you need to know within a shorter time frame when an event fires, this technique may not be the best fit. This is when you start looking at more advanced monitoring solutions. The shorter the interval, the more expensive the operation and software solution.

To create the event subscription, you use the Register-CimIndicationEvent cmdlet. This cmdlet creates a subscription to WMI events based on your query. You can also specify a source identifier, which is a unique name for the subscription. This is useful when you want to manage or unregister the subscription later.

Register-CimIndicationEvent -Query $query -SourceIdentifier NewProcess

> You must run this command in an elevated PowerShell session.

This event subscription exists for the duration of the PowerShell session where it was created. Run Get-EventSubscriber to see the subscription.

PS C:\>Get-EventSubscriber

SubscriptionId   : 2
SourceObject     : Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationWatcher
EventName        : CimIndicationArrived
SourceIdentifier : NewProcess
Action           :
HandlerDelegate  :
SupportEvent     : False
ForwardEvent     : False

This event subscriber will monitor for new processes every 5 seconds. When a matching event fires, an event will be raised and captured. Use Get-Event to see the captured events.

PS C:\> Get-Event

ComputerName     :
RunspaceId       : 4d199c26-8348-4783-8148-cbb9ff830bc8
EventIdentifier  : 1
Sender           : Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationWatcher
SourceEventArgs  : Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationEventInstanceEventArgs
SourceArgs       : {Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationWatcher, }
SourceIdentifier : NewProcess
TimeGenerated    : 9/3/2025 10:42:56 AM
MessageData      :

ComputerName     :
RunspaceId       : 4d199c26-8348-4783-8148-cbb9ff830bc8
EventIdentifier  : 2
Sender           : Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationWatcher
SourceEventArgs  : Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationEventInstanceEventArgs
SourceArgs       : {Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationWatcher, }
SourceIdentifier : NewProcess
TimeGenerated    : 9/3/2025 10:42:56 AM
MessageData      :

ComputerName     :
RunspaceId       : 4d199c26-8348-4783-8148-cbb9ff830bc8
EventIdentifier  : 3
Sender           : Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationWatcher
SourceEventArgs  : Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationEventInstanceEventArgs
SourceArgs       : {Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationWatcher, }
SourceIdentifier : NewProcess
TimeGenerated    : 9/3/2025 10:43:01 AM
MessageData      :
Want to read the full issue?
GitHub Bluesky LinkedIn About Jeff
Powered by Buttondown, the easiest way to start and grow your newsletter.