Your Goto Guide for Working with Windows WMI Events and PowerShell

choubertsprojects

VPN offers!

1. NordVPN

2. Surfshark

3. ExpressVPN

Windows Management Instrumentation (WMI) is a platform that allows users to manage Windows-based computers and devices remotely. With the introduction of PowerShell in Windows 8, WMI events have become accessible using an event query language called CIM. This article provides guidance on how to integrate these technologies together for better results.

The “wmi temporary event subscription” is a Windows Management Instrumentation (WMI) command that allows users to subscribe to WMI events. It can be used in conjunction with PowerShell and the EventLog module.

Your Goto Guide for Working with Windows WMI Events and PowerShell

Did you realize that almost every operation in Windows may be monitored? No, you do not need to purchase any expensive software. Events such as when services start and stop, when someone creates a file or folder, and more are already monitored by the infrastructure through Windows Management Instrumentation (WMI) events.

WMI events are not a PowerShell feature, however PowerShell is one of the simplest methods to use WMI events and construct some useful tools. In this step-by-step tutorial, you’ll learn how to use PowerShell to take advantage of WMI events and construct some useful monitoring tools!

Let’s get this party started!

Prerequisites

In this hands-on session, you’ll witness a lot of demonstrations. If you want to follow along with any of the demonstrations, you’ll need the following items:

  • Windows 7+ or Windows Server 2012+ – Windows Server 2019 will be used in this lesson.
  • I’m a member of the local administrators group, and I’m logged in as that user.
  • PowerShell 5.1 or PowerShell 6+ on Windows – PowerShell v7.1.2 will be used in this course.

WMI and CIM are two terms that need to be understood.

Before you dive into WMI events, you need first learn about the architecture that supports them. Although this article will not go into great detail about WMI, you can always turn to Microsoft’s WMI documentation for further information.

WMI and the data model that goes with it CIMs (Common Information Models) are models built into Windows that store just about every piece of information you need about Windows and what’s running on it in a repository.

Administrators utilize WMI and CIM to administer Windows both locally and remotely. Admins may query information on a Windows system using WMI or CIM, including installed apps, service status, file system files, and just about anything else.

Many corporate monitoring systems capture operating system and application health information using WMI and CIM. But you don’t need to spend a lot of money on a monitoring solution to use WMI; you already have PowerShell!

Let’s start with the two most fundamental aspects, and then we’ll go through the remaining elements as we go:

  • Classes are the events and attributes that a program, like PowerShell, may use to access and change data. A namespace is where classes are stored.
  • The namespace acts as a container for all WMI-related classes. Consider it a My Picture folder that contains photo-related items. There are many namespaces, the most popular of which being CIMv2, which contains the majority of the OS classes. However, all of the namespaces are grouped together under the Root namespace.

WMI (Windows Management Instrumentation) ArchitectureWMI (Windows Management Instrumentation) Architecture

CIM vs. WMI

WMI and CIM are two techniques for interacting with a Windows system’s repository, which contains a lot of data, and working with WMI events (more on that later). However, there are a few distinctions between the two techniques, the most notable of which being how administrators engage with them remotely.

WMI was the first (and only) means to communicate with the repository, and it was introduced with Windows NT4. When you use WMI to administer a Windows system, Windows employs the Distributed Component Object Model (DCOM) (DCOM). DCOM is a remote protocol that WMI utilizes to provide data from a Windows machine’s data repository.

DCOM employs Remote Procedure Call to function across a network (RPC). RPC employs dynamic port ranges to interact across a network, which may be difficult for firewalls and Network Address Translation (NAT) devices to handle.

Check see the article Test RPC Connections with Dynamic Ports if you’re experiencing problems with RPC.

Microsoft chose CIM to give a more contemporary interface for working with the Windows data store. CIM employs WS-MAN (Web-Service for Management) instead of RPC, an HTTP protocol that is considerably more suited for remote management.

WMI and CIM may be used interchangeably in this and other articles. A WMI repository is the data repository with which both management techniques interact. WMI is referred to almost universally, although CIM is often used in PowerShell cmdlets.

CIM vs. WMI and PowerShell

Fortunately, when it comes to WMI and CIM with PowerShell, you have a few alternatives. Both methods of communicating with the data repository are supported by PowerShell. You may see numerous Wmi cmdlets while running the Get-Command command in PowerShell, such as Get-WmiObject, Invoke-WmiMethod, Remove-WmiObject, Register-WmiEvent, and Set-WmiInstance.

You’ll also find cmdlets like Get-CimInstance, Get-CimClass, and Remove-CimInstance if you’re using Windows PowerShell 3 or above (which you should be!).

Which cmdlets in PowerShell should you use? The solution is straightforward: CIM cmdlets. Microsoft is concentrating on the CIM standard. Even with PowerShell Core, the WMI cmdlets aren’t accessible!

How to Work with WMI in PowerShell is a related article.

The Basics of WMI Querying

You must first learn how to query WMI using PowerShell before diving into WMI events. The most typical usage of WMI data is to query information from the WMI repository.

The Get-CimInstance cmdlet is your buddy in the PowerShell world when it comes to querying WMI data. There are a number different methods to query WMI data using this cmdlet. However, the Query parameter will be the center of this course. To query WMI, use the Query parameter to specify a Windows Query Language (WQL) query.

You could want to locate all of the WMI instances in the Win32 Service class, for example. You’d use the Select * from Win32 Service query, which is similar to SQL. WMI is told to return all attributes of each instance discovered by the asterisk (*).

‘Select * from Win32 Service’ from Get-CimInstance -Query

Using WMI Query to Retrieve Windows ServicesUsing WMI Query to Retrieve Windows Services

You identified all instances of each service in the Win32 Service class in the previous example, but what if you just want to locate a few? You’d utilize the WHERE clause in such situation. The WHERE clause sets a filter that only returns instances that meet a set of criteria.

Get-CimInstance is told to only return instances if the instance property matches a certain value using the WHERE clause. For instance, you could only wish to locate service instances with the State attribute set to Running. If that’s the case, you’d use the WHERE clause to specify State=’Running,’ as illustrated below.

-Query Get-CimInstance “Where State=’Running’, select * from Win32 Service”

Get-CimInstance only returned service instances with the State field set to Running, as seen below.

Only services in a running condition will be returned.Only services in a running condition will be returned.

WMI Actions: WMI’s Actions

WMI is a big database that includes information about thousands of things in Windows. You may get that data by querying it, like you did before, but it also contains a lesser-known feature: WMI events.

Hundreds of events might be happening in Windows at any one moment. A WMI event is often generated when you use Windows functions such as creating files, stopping and resuming services, installing software, or anything else.

A WMI event may be used to expose almost every operation done on Windows. When a user performs a task on Windows, the operating system generates an event using its own infrastructure. By default, you won’t be able to observe these events since they occur in the background. You must subscribe to these events in order to view them.

Using PowerShell to Create a Service Monitoring Script

Rather than boring you with a ton of material, let’s construct a helpful tool to show how WMI events function. Because WMI events occur anytime a Windows event occurs, you may use them to construct some useful monitoring tools.

If the status of a Windows service on a crucial server changes, you may want to send a message to a log file. Then, when those activities occur, you can subscribe to the WMI events that are triggered. When you subscribe to an event and the event triggers, you can do things like log to a file, send an email, and pretty much everything else PowerShell can do.

A simple PowerShell script may be a wonderful poor man’s monitoring tool instead of purchasing a costly monitoring package! Open your PowerShell console if you’re ready, and let’s get started!

Choosing a CIM Class

Events are contained in classes in WMI, much like static instances. These classes include all of the static data you requested before, as well as the code that triggers modifications to those instances. The Microsoft documentation has a list of all CIM classes.

Run the Get-CimClass cmdlet without any arguments to discover all CIM classes. By default, the Get-CimClass cmdlet retrieves all classes from the ROOT/cimv2 namespace. Nearly all relevant Windows classes are kept in the ROOT/cimv2 namespace, which is the “main” namespace.

However, as you can see below, a large number of classes are returned.

Choosing a CIM ClassChoosing a CIM Class

Perhaps you’ve dug a little further and discovered that all Windows services are housed in the Win32 Service folder. As a result, when you know the name of the class, utilize the ClassName argument to provide it, as illustrated below.

Win32 Service -ClassName Get-CimClass

CimClass is a parameter that you can get.CimClass is a parameter that you can get.

Choosing a CIM Class Properties

After you’ve determined which class to investigate, you’ll need to choose which property to investigate. An event is triggered when the value of an instance property changes (or when a complete instance is created or destroyed). You must record the change in state. To do so, you must first choose the attribute you want to track.

Inspect the CimClassProperties PowerShell object property on the CIM class instance you queried in the last step to locate that property.

(Win32 Service -ClassName Get-CimClass).CimClassProperties

One of the properties is the State property, as seen below.

The Win32 Service Properties include the following:The Win32 Service Properties include the following:

It’s time to subscribe to the WMI event now that you know the CIM class and property you’d want to watch.

The High-Level Overview of Creating a WMI Event Subscription

If you’ve never setup a WMI event subscription before, it might be a difficult undertaking. Let’s start with the forest before the trees and define the essential stages to assist you stay on track.

There are four basic stages to creating a WMI event subscription:

  1. Making the WQL query — Just like with static data, you’ll need to make a WQL query that matches the kind of WMI event you’re looking for. However, unlike accessing the datastore, the query needs include a few more complex components, such as system classes and checking cycles (more on those later).
  2. How to Make an Event Filter — After you’ve finished with the WQL query, you’ll need to do the same with the event filter. The WQL query is registered in CIM by the event filter.
  3. Consumer Development — When the event filter query returns a change in the class, the consumer determines what action to take. When a service status is started, halted, generated, or withdrawn, for example, the customer initiates an action.
  4. Binding the event filter to the consumer — This is the glue that holds the Windows WMI query together. When the event filter receives a match, the binding alerts the consumer.

When you combine all of these elements, you obtain a subscription.

An example of a WMI event subscription in its simplest formAn example of a WMI event subscription in its simplest form

WQL Query Construction

A WQL query for a WMI event looks a little different from a normal Get-CimInstance query. A example WMI event query is shown below.

Select * from <system class> within <checking cycle> where TargetInstance ISA ‘<class name>’

Because the WQL query may seem intimidating at first, let’s dissect it and learn how each component functions.

The System Class is a kind of system.

You noticed that you’d want to be alerted when an instance of the Win32 Service class is changed in the Get-CimInstance example. This class is still required, however instead of a WQL query that looks like this:

Choose * from the Win32 Service drop-down menu.

Instead, the query will begin as follows. The primary class you’re looking for isn’t the one with the instance you want to be alerted about. The class is instead a system class.

Select * from <system class>

System classes are internal classes that indicate the sort of change that occurs as a result of the event. There are four sorts of system classes in a WMI event:

  • InstanceModificationEvent — Checks for any changes in the value of a property on a class instance. You’ll use this class if you want to keep track of a property value called Status on a Win32 Service instance (service).
  • Checks for new instances using InstanceCreationEvent. You’d use this system class if you wanted to keep track of any new services that were established, for example.
  • InstanceDeletionEvent — Checks for any instances that have been deleted. This system class might be used, for example, to monitor services that have been withdrawn.
  • This system class checks for all forms of events, including change, creation, and deletion.

The beginning of the WQL query for our monitoring script will be as follows:

Choose * from the __InstanceModificationEvent collection.

The names of WMI system classes usually begin with two underscores (__), followed by the class name.

The Cycle of Checking

Next, you have The Cycle of Checking. The Cycle of Checking includes the keyword within and a value representing a polling interval represented in seconds.

WMI events are not real-time, so you must define a certain interval for your subscription to check for changes. If, for example, you set The Cycle of Checking to 10, the subscription will check for a change from the last polling cycle every 10 seconds. If a change is found, it triggers the consumer.

If an instance is changed, created or removed depending on The System Class is a kind of system. within the polling interval the change won’t be detected! Consider the frequency you need but make sure it’s CPU and memory friendly!

For the tutorial’s service monitoring example, let’s set The Cycle of Checking to 10 to poll WMI every 10 seconds for a change in a Windows service. The WQL query is growing!

Choose * from the __InstanceModificationEvent collection. within 10

The Filtering System

Finally, to complete the WQL query, you must define a filter to limit the instances returned from The System Class is a kind of system.. You must define that filter in the form below. In this case, the CIM class you’d like to monitor is called the TargetInstance.

where Targetinstance ISA ‘<class name>’

ISA is a query operator that applies a query to a class’s subclasses.

Since the tutorial is building a subscription to monitor Windows services, you’d create The Filtering System like below:

where ISA ‘Win32 Service’ is the target instance

As is, The Filtering System looks for all instances of Win32_Service. If you’d like only to monitor a single property, perhaps a specific service, you’d use the AND operator.

where ISA ‘Win32 Service’ is the target instance AND Targetinstance.name=’bits’

The AND and OR operators combine two or more criteria to get more precise results.

As seen in the code excerpt below, the tutorial filter (and the full query) is now complete.

Choose * from the __InstanceModificationEvent collection. within 10 where ISA ‘Win32 Service’ is the target instance AND Targetinstance.name=’bits’

How to Make an Event Filter

The remainder of the procedure is much simpler to grasp now that you have the query filter! To utilize that query, you must now construct the event filter. An event filter is a CIM instance that belongs to the Root/subscription namespace and is part of the __EventFilter class.

A code sample containing everything you need may be found below. The WQL query is assigned to the $FilterQuery variable in the script below. It then constructs a hashtable with all of the characteristics and values that the event filter requires. Finally, the New-CimInstance cmdlet is used to construct the event filter.

The CIM instance object that results is then saved in a variable ($CIMFilterInstance) for subsequent usage.

$FilterQuery=”Choose * from the __InstanceModificationEvent collection. within 10 where ISA ‘Win32 Service’ is the target instance” $CIMEventFilterProperties = @{ ## The name of the event filter. This can be anything related. Name=”MyServiceFilter” ## The namespace for the targetted class, for example, the targetted class for ## **Win32_Service** is Root/CIMv2 EventNameSpace=”Root/CIMV2″ ## The query language, usually **WQL**. QueryLanguage=”WQL” ## The query to use. Query=$FilterQuery } $CIMFilterInstance=New-CimInstance -ClassName __EventFilter -Namespace “Root/SubScription” -Property $CIMEventFilterProperties

Run Get-CimInstance now to see whether the new CIM instance of __EventFilter was generated.

-Namespace root/subscription -ClassName __EventFilter Get-CimInstance

The Event Filter was successfully created, and the Windows WMI Query was registered.The Event Filter was successfully created, and the Windows WMI Query was registered.

Consumer Development

Next, it’s time to create the consumer or the action that will happen when Windows triggers the WMI event. When Consumer Development, you have a few options depending on the type of action you’d like to trigger.

To prevent someone from changing the EXE with a malicious binary, make sure the executable’s ACL is set appropriately.

Let’s use the LogFileEventConsumer consumer type in this lesson to write to a log file whenever the service matched in the WQL query changes.

@ ## $CIMCOnsumerProperties = $CIMCOnsumerProperties = $CIMCOnsumerProperties = $CI Name=”MyServiceConsumer” ## The file path and name to which the log writes when the event is triggered by the script in the **Root/Subscription** namespace. ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## The text that should be written in the log. ## percent TargetInstance.WMIProperty percent may be used to add a variable. The **Caption** and **State ##** are utilized in this example. “The Service percent TargetInstance.Caption percent has been changed to percent TargetInstance.State percent ” Text = “The Service percent TargetInstance.Caption percent has been changed to percent TargetInstance.State percent ” $CIMEventConsumer=New-CimInstance -ClassName LogFileEventConsumer -Namespace ‘ROOT/subscription’ -Property $CIMEventConsumer=$CIMEventConsumer=$CIMEventConsumer=$CIMEventConsumer=$CIMEventConsumer=$CIMEventConsumer=$CIME $CIMCOnsumerProperties ## $CIMCOnsumerProperties ## $CIMCOnsumerPro Other customers’ examples NTEventLogEventConsumer ################################################################################################################################################## @(##’@(##’@(##’@(##’@ percent TargetInstance.Caption percent has been replaced with percent TargetInstance. ##) ##[email protected]%%%%%%%%%%%%%%%%%%%%%%%%% ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## EventID =[UInt32] 7040 ## The Event ID to utilize ## ## – **0**: ## ## – **0**: ## ## – **0**: ## ## – **0**: ## ## Error Event ## ## – **2**: Warning Event ## ## – **4**: Information Event ## ## – **8**: Success Audit Event ## ## – **16**: Event of Failure Audit ## [UInt32] EventType 1 #Information ## ## The Event Source’s name. ## “Service Control Manager” is the source name. ## [UInt16] as a category ## ## ## ## ## ## ## ## ## The amount of **InsertionStringTemplates** lines ## =[UInt32] NumberOfInsertionStrings $Template.Length # ## # The text of the message that will appear in the Windows EventLog record. InsertionStringTemplates = InsertionStringTemplates = InsertionStringTemplates = Inserti $CIMEventConsumer=New-CimInstance -ClassName $Template ## ## $CIMEventConsumer=New-CimInstance -ClassName -Namespace NTEventLogEventConsumer -Property ‘ROOT/subscription’ $CIMCOnsumerProperties ############################################################################################################################################################################ ## ## ## ## ## ## ## ## ## For the customer, a one-of-a-kind moniker. ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## The path and parameter for the program that should run when the event occurs. ## CommandLineTemplate =’pwsh.exe c:myscript.ps1 -ServiceName percent TargetInstance.name percent -NewState percent TargetInstance.newState.newState.newState.newState.newState.newState.newState.newState.newState.newState.newState.newState.newState.new ## ## ## ## ## ## ## ## ## ## ## (Optional) After a certain amount of seconds, the program will be terminated. This is useful for safeguarding your server’s resources. ## ##$CIMEventConsumer=New-CimInstance -ClassName CommandLineEventConsumer -Namespace ‘ROOT/subscription’ -Property $CIMEventConsumer=New-CimInstance -ClassName CommandLineEventConsumer -Namespace ‘ROOT/subscription’ -Property $CIMEventConsumer=New-CimInstance -Namespace ‘ROOT/ $CIMCOnsumerProperties ################################################################################################ #################################################################### ‘The File Server changed percent Targetinstance,’ says the email message body. Name percent, TargetInstance percent ## [email protected]%%%%%%%%%%%%%%%%%%%%%% ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## The sender’s e-mail address. ## FromLine ='[email protected]’ ## ## the email address of the receiver ## ToLine = ‘[email protected]’ ## SMTP Server to which the message should be sent. ## SMTPServer = ‘MySMTPServer.MyDomain.Com’; ## SMTPServer = ‘MySMTPServer.MyDomain.Com’; ## ## ## ## ## ## ## ## ## ## The topic of the mail is ## Subject = ‘File Server Changed…’ $CIMEventConsumer=New-CimInstance -ClassName SMTPEventConsumer -Namespace ‘ROOT/subscription’ -Property $CIMCOnsumerProperties ## ##$CIMEventConsumer=New-CimInstance -ClassName SMTPEventConsumer -Namespace ‘ROOT/subscription’

Each consumer class has its unique set of arguments, therefore use (Get-CimClass -ClassName __NTEventLogEventConsumer) to get additional information about each one. CimClassProperties.

After you’ve built the consumer, use Get-Ciminstance to verify its existence.

-Namespace Root/Subscription -ClassName LogFileEventConsumer Get-CimInstance

Consumers who have entered the appropriate criteria have been registered.Consumers who have entered the appropriate criteria have been registered.

Connecting the Event Filter and the Consumer

Finally, it’s time to finish this subscription by connecting the event filter and the consumer! As you would expect, building the binding necessitates the creation of yet another CIM instance. You’ll need to construct a new instance of the __FilterToConsumerBinding class this time.

The below code snippet is using the two instances created earlier (The Filtering System and the consumer) as a hashtable which defines the properties necessary to create a new instance. It’s then passed to New-CimInstance as before to create the binding.

[email protected] [Ref] [Filter] [Ref] [Ref] [Ref] [Ref] Consumer $CIMFilterInstance = [Ref] $CIMEventConsumer is a consumer of CIMEvents. $CIMBinding = New-CimInstance -ClassName __FilterToConsumerBinding -Namespace “root/subscription” -Property $CIMBinding = $CIMBinding = $CIMBinding = $CIMBinding = $CIMBinding = $CIMBinding = $CIMBinding = $CIMBind $CIMBindingProperties

Run Get-CimInstance again to double-check that the binding has been generated.

Get-CimInstance -Namespace Root/Subscription -ClassName __FilterToConsumerBinding Get-CimInstance -Namespace Root/Subscription Get-CimInstance -Namespace Root/Subscription Get-CimInstance -Namespace Root

As you can see, the binding has information about both The Filtering System and the Consumer.

Binding SpecificationsBinding Specifications

Subscription Evaluation

You’ve completed the task! It’s time to put your hard work to the test! All you have to do now is alter the BITS service status to check whether PowerShell publishes an item to the C:MyCIMMonitoring.txt log file.

Stop or start the BITS service, or simply restart it using the Restart-Service cmdlet, depending on its condition.

Restart-Service | Get-Service -Name BITS

Wait for about 10 seconds and check the C:MyCIMMonitoring.txt. You should now see the Text in the log file you defined when Consumer Development.

Get-Content -Path C:MyCIMMonitoring.txt Get-Content -Path C:MyCIMMonitoring.txt Get-Content -P

Changes in service are identified.Changes in service are identified.

Check the Windows event log under the route Applications and Services LogMicrosoftWindowsWMI-ActivityOperational to keep track of all WMI event activity.

Stopping the Subscription and Cleaning It Up

It’s time to clear up the subscription after you’ve finished utilizing it. The event filter, consumer, and binding instances must all be removed to stop and delete the WMI event subscription.

Remove the event filter by using Get-CimInstance to locate the instance.

-Namespace root/subscription -ClassName __EventFilter Get-CimInstance | Remove-CimInstance ## For more than one instance -Namespace root/subscription -ClassName __EventFilter Get-CimInstance | where {$.name -like “MyServiceFilter”} | Remove-CimInstance

EventFilter is a registered event filter.EventFilter is a registered event filter.

After that, delete the customer in the same manner.

-Namespace Root/Subscription -ClassName LogFileEventConsumer Get-CimInstance | Remove-CimInstance ## For more than one instance -Namespace Root/Subscription -ClassName LogFileEventConsumer Get-CimInstance | where {$_.Name -like “MyServiceConsumer”} | Remove-CimInstance

Getting the LogFileEventConsumer Class's ConsumerGetting the LogFileEventConsumer Class’s Consumer

Remove the binding at the end. The characteristic that is used to locate the binding is a little different. The binding instance contains a Filter property instead of a Name property, which is really an object with a Name property.

Get-CimInstance -Namespace Root/Subscription -ClassName __FilterToConsumerBinding Get-CimInstance -Namespace Root/Subscription Get-CimInstance -Namespace Root/Subscription Get-CimInstance -Namespace Root | Where-Object {$_.Filter.Name -like “MyServiceFilter”} | Remove-CimInstance

Obtaining information about the Binding.Obtaining information about the Binding.

Conclusion

WMI/CIM is a useful and effective tool for gathering information about Windows and monitoring it via WMI events. WMI events provide you a lot of insight and allow you to respond quickly to any problems, making it easy to automate a response for each event.

Check out How to Track Active Directory Changes with WMI Events for a wonderful real-world example.

The “register-wmievent” command is a PowerShell cmdlet that allows users to register WMI events. This tool can be used with Windows event logs, such as the Security log or the System log.

Frequently Asked Questions

How do I use WMI in PowerShell?

A: In PowerShell, you can use the WMI namespace to get information about your system and any of its components.

How do I use WMI to get information about remote computers?

A: WMI is an acronym for Windows Management Instrumentation. It allows a computer to have one or more remote computers added as targets to the local machines management console, which can then be used by tools such as netsh and PowerShell.

How do you query a WMI class?

A: I ask Microsoft for the answer.

Related Tags

  • powershell wmi event watcher
  • wmi event logs
  • list wmi event subscriptions
  • __instancecreationevent
  • win32_processstarttrace