WMI Timer Events in PowerShell using Win32_LocalTime


This is not a part of the WQL series I am doing. I happend to take a look at the WMI timer events while providing feedback to an upcoming (cool) PowerEvents module by Trevor (@pcgeek86). BTW, this module will be released on November 30th. So, watch out for the annoncement.

Coming to the subject of this post, in WMI, there are 3 types of events possible. They are Timer events, Intrinsic events, and extrinsic events. My WQL series will soon cover intrinsic and extrensic events. Very few people have written about WMI timer events in the past but this particular post on The SysAdmins blog discusses good amount of details.

In today’s post, I am going to write about WMI timer events in PowerShell and how to use Register-WMIEvent cmdlet to create a temporary consumer to consume these events. In general, WMI timer events are generated by WMI infrastructure at a point in time. In the good old days of Windows 2000, we had to capture these by creating an instance of classes derived from the __TimerInstruction class. Also, there are two types of timer events.

  1. Absolute Timer Events occur on a specific day at a specific time.
  2. Interval Timer Events are events that occur periodically at specified intervals. For example, every 30 minutes.

Prior to Windows 2003, we have had to use __AbsoluteTimerInstruction class and __IntervalTimerInstruction class to define these events. However, that isn’t necessary anymore with the introduction of Win32_LocalTime or Win32_UTCTime WMI classes. With these two classes, we can use the standard WMI eventing model to consume timer events.

Let us take a look at Win32_LocalTime. This class represents an instance of Win32_CurrentTime.

As you see in the above screenshot, an instance of this class represents the current date and time. There are a few special properties that tell you which quarter of the year, week in the current month, and etc. Do refer to the MSDN link for this class and read about the properties. Especially, the DayOfWeek property. It always indicates Sunday as zero irrespective of the system culture and langauge settings.

Since, these this class supports standard WMI eventing model, we can use an intrinsic event query to consume these events. For example,

1
2
3
4
#Setup WQL query
$query = "SELECT * FROM __InstanceModificationEvent WHERE TargetInstance ISA 'Win32_LocalTime'"
#Register WMI Event
Register-WmiEvent -Query $Query -SourceIdentifier "Event-Every-Second" -Action { Write-Host "Event Received" }

will result in displaying “Event Received” message at the console every one second. This is because the event fires every one second and that is the smallest time segment supported. Now, this won’t be very useful unless you want to flood your consumer with a bunch of useless messages every one second. Let us look at another example:

1
2
3
4
5
6
7
#Setup WQL query
$query = "SELECT * FROM __InstanceModificationEvent WHERE TargetInstance ISA
            'Win32_LocalTime' AND TargetInstance.Hour=14
                              AND TargetInstance.Minute=30
                              AND TargetInstance.Second=0"
#Register WMI Event
Register-WmiEvent -Query $Query -SourceIdentifier "Event-Every-Day-14.30PM" -Action { Write-Host "Event Received" }

In this example, we use WQL query to register for a WMI event that fires every day at 14.30 hours. Note that the hours value is in 24 hour format. Now, this is useful. I can use the -Action script block to do something better like running a backup script when this event fires. Similarly, you can also create event registrations for events occurring on specific day of every quarter (Quarter) or specific week (WeekInMonth) of every month.

WMI Timer events can be used to create some very advanced scheduling jobs. Register-WMIEvent creates a temporary consumer but just imagine being able to create a permanent consumer and use that for scheduling several administrative tasks. I will update this post once Trevor (@pcgeek86) releases his PowerEvents module and show you some cool tricks.

However, here is the catch: There is a bug that causes DayOfWeek to stop triggering any timer events. Update: I posted this question on DayOfWeek at http://social.msdn.microsoft.com/Forums/en-US/etw/thread/06b7ae7f-737e-47f2-9ae2-a5b8d4c125a9

1
2
3
4
5
6
7
8
#Setup WQL query for DayOfWeek
$query = "SELECT * FROM __InstanceModificationEvent WHERE TargetInstance ISA
            'Win32_LocalTime' AND TargetInstance.=3
                              AND TargetInstance.Hour=12
                              AND TargetInstance.Minute=16
                              AND TargetInstance.Second=0"
#Register WMI Event
Register-WmiEvent -Query $Query -SourceIdentifier "Event-Every-Tuesday-12-16PM" -Action { Write-Host "Start backup" }

This is a dissappointing bug and I am going to check if MS has any answer. Their documentation for Win32_LocalTime uses a WQL query that has DayOfWeek property. I’d experimented with the same query in PowerShell, VBScript & C#. It worked no where. So, timer events are quite useful in creating advanced scheduling jobs but the current bug is keeping it away from “real” world use.

I will update this post with the details I find out or get from Microsoft. Keep watching this space.

Share on: