>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.

Advertisements

>When Dispose() isn’t enough

>A while back I had a discussion with another developer on my current project about Dispose() and the need to call an object’s Close()/Stop()/etc methods before calling Dispose(). I was of the opinion that classes implementing IDisposable would be smart enough to do whatever cleanup was necessary without the caller needing to also call Close() or Stop() or whatever other method “disables” that object’s functionality. He argued that you may not always be able to rely on Dispose() being implemented properly. I came back with the System.Data.SqlClient.SqlConnection object and showed in Reflector that it does indeed call Close() during Dispose(bool). See, I’m right!

Well, today I had to eat my words and agree with him (You were right Dave! 🙂 ). We use WMI even notifications to raise scheduled events by subscribing to changes on Win32_LocalTime. While trying to diagnose why we sometimes get a “Quota Violation” exception when subscribing I opened up Reflector to look at the ManagementEventWatcher class. The ManagementEventWatcher has a Stop() method which disables event notifications. The bad part is that it inherits from System.Component.ComponentModel (which implements IDisposable) but does not override Dispose(bool). This results in leaking event subscriptions when a Start()’d ManagementEventWatcher is Disposed without first calling Stop().

So, lesson learned… unless you know for sure (ie. you’ve checked using Reflector), always call the “disabling” method (Stop(), Close(), whatever) before Disposing your IDisposable objects. In a perfect world any object implementing IDisposable would correctly clean up after itself, but in the real world that’s not the case!