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 :