Tuesday, June 26, 2007

C# ManagementEventWatcher using Win32_LocalTime and DayOfWeek masks (WMI)

We are using WMI notification events for scheduling activities on our current project. This makes scheduling events on a periodic basis very easy as you don't have to set up timers, calculate intervals to the next event, reset the timer, etc. With WMI events you can simply set up a mask on the local time (or UTC if you prefer) and then whenever that mask matches the system clock you get an event.

We are using Win32_LocalTime for our schedules and we came across a bug in using WMI notification events and the DayOfWeek property on Win32_LocalTime. Turns out that you cannot specify a single DayOfWeek (they number from 0 to 6 where 0=Sunday) on a schedule. WMI simply will not raise an event even when the mask matches.

So, for example, the following query will cause an event to be raised every Tuesday and Wednesday at 3:00 PM (WMI events have a granularity to the second, so no subsecond event notifications):

SELECT * 
FROM __InstanceModificationEvent
WHERE TargetInstance ISA 'Win32_LocalTime'
AND
(
TargetInstance.DayOfWeek = 2
OR TargetInstance.DayOfWeek = 3
)
AND
(
TargetInstance.Hour = 15
AND TargetInstance.Minute = 0
AND TargetInstance.Second = 0
)

However, if you just want events on Tuesday WMI seems to simply ignore the registration:
SELECT * 
FROM __InstanceModificationEvent
WHERE TargetInstance ISA 'Win32_LocalTime'
AND
(
TargetInstance.DayOfWeek = 2
)
AND
(
TargetInstance.Hour = 15
AND TargetInstance.Minute = 0
AND TargetInstance.Second = 0
)

Our solution is to register for every day of the week and then when the event is raised, simply filter it out if we don't really want an event on that day.

The interesting thing is that masking on the day of the month (Day property) for a single day works just fine.

1 comment:

Charles Strahan said...

That's pretty cool, Jeremy. Do you suppose you could share a snippet of C# that does the WMI querying?

Cheers,
-Charles