WMI Provider Extensions in .NET 3.5 – Publishing Events and Advanced Topics

April 30, 2008

tags:
4 comments

The previous posts in this series described various mechanisms of communication from the WMI consumer to the WMI provider – including read-only properties, read-write properties and methods. However, publishing events from a WMI provider is the only scalable option of providing changing contextual information as it occurs. Pulling the information on demand is not an option because it doesn’t scale.

In this post, we will use the BaseEvent class or the [InstrumentationClass] attribute to publish events from a WMI provider.

Publishing events from a WMI provider is not supported by the WMI Provider Extensions for .NET 3.5. It is only supported by the .NET 2.0 implementation. Therefore, in order to publish events from your application, the [Instrumented] assembly-level attribute from .Net 2.0 must be placed on the assembly, and another installer class derived from DefaultManagementProjectInstaller (as opposed to DefaultManagementInstaller) must be added to the project. The following code demonstrates the assembly-level attribute and installer class required to support events from a WMI provider.

[assembly: Instrumented(@"root\MyApplication")]

 

[RunInstaller(true)]

public class OldInstaller :

    DefaultManagementProjectInstaller {}

Note that using the [WmiConfiguration] assembly-level attribute and DefaultManagementInstaller-derived installer (which we used in the previous posts) is not enough to publish events. To properly publish events to the required namespace, the [Instrumented] assembly-level attribute and DefaultManagementProjectInstaller-derived installer are required. It is possible to mix both approaches in the same assembly.

An event that can be published from a WMI provider is represented as a simple managed class. The class contains properties which constitute the event data. The following code demonstrates an event class that can be published whenever the CPU temperature rises above a certain threshold.

public class CpuTemperatureAboveThresholdEvent : BaseEvent

{

    public float ActualTemperature { get; private set; }

    private CpuTemperatureAboveThresholdEvent(

        float actualTemperature)

    {

        ActualTemperature = actualTemperature;

    }

    public static void Publish(float actualTemperature)

    {

        new CpuTemperatureAboveThresholdEvent(

            actualTemperature).Fire();

    }

}

To publish this event, we can use the static Publish method we have just written:

CpuTemperatureAboveThresholdEvent.Publish(85.0f);

An alternative to deriving the event class from the BaseEvent type is using the [InstrumentationClass] attribute and specifying that the instrumentation type for the class is an event. The following code demonstrates how the event can be rewritten using this paradigm:

[InstrumentationClass(InstrumentationType.Event)]

public class CpuTemperatureAboveThresholdEvent

{

    public float ActualTemperature { get; private set; }

    private CpuTemperatureAboveThresholdEvent(

        float actualTemperature)

    {

        ActualTemperature = actualTemperature;

    }

    public static void Publish(float actualTemperature)

    {

        Instrumentation.Fire(

            new CpuTemperatureAboveThresholdEvent(

                actualTemperature));

    }

}

Note that the only changes are that the class doesn’t derive from BaseEvent, and that to publish the class the Instrumentation.Fire method must be called instead of the Fire method inherited from BaseEvent.

Visual Studio’s Server Explorer features the support necessary for subscribing to events published by a WMI provider. Right click the Management Events node and select Add Event Query. In the dialog displayed, search for your class name (in our case, CpuTemperatureAboveThresholdEvent). A sub-node appears under the Management Events node – this node is the container for the events consumed by Server Explorer. These events should also appear in the Output window as soon as they are published. In a WinForms application or any other designer surface, it’s possible to drag and drop the event query node to create and configure an instance of the ManagementEventWatcher class ,enabling you to consume the event at runtime.

The ManagementEventWatcher class can be used directly without Server Explorer’s mediation. The following code demonstrates registering to the CpuTemperatureAboveThresholdEvent described in the previous section and outputting the CPU temperature when the event is published.

ManagementEventWatcher watcher =

    new ManagementEventWatcher(@"root\MyApplication",

        "SELECT * FROM CpuTemperatureAboveThresholdEvent");

watcher.EventArrived += (o, e) =>

    Console.WriteLine(e.NewEvent["ActualTemperature"]);

watcher.Start();

Is is time to outline some of the advanced topics that are outside the scope of this series.

References between WMI Objects

A reference between WMI objects has to be established using a property decorated with a [ManagementReference] attribute. The attribute’s parameter specifies the type of the referenced object. A standard object reference will not work with WMI without this attribute.

Enumerators

WMI classes can implement an enumeration static method to dynamically discover or create WMI object instances. This can be accomplished by decorating a method wit the [ManagementEnumerator] attribute and returning an IEnumerable. This static method can then be called instead of issuing a standard object query; it enables dynamically creating the WMI instances instead of publishing them in advance.

Create and Remove Methods

Instances methods on a WMI class can create a new instance of the WMI class. These methods must have the same signature as the class binding constructor (decorated with [ManagementBind]) and be decorated with the [ManagementCreate] attribute.

Similarly, a method can be denoted as a cleanup method for a MWI class instance. This method must not have any parameters and must return void, and be decorated with the [ManagementRemove] attribute.

Dynamic Registration

Instead of performing registration with the InstallUtil.exe tool, it is possible to dynamically register and unregister assemblies or types containing WMI provider information. The InstrumentationManager.RegisterAssembly and InstrumentationManager.UnregisterAssembly methods provide dynamic registration and unregistration for all the types in the specified assembly. The InstrumentationManager.RegisterType and InstrumentationManager.UnregisterType methods provide dynamic registration and unregistration for the specified specific type.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

4 comments

  1. Alois KrausAugust 5, 2008 ב 8:08 AM

    Hi Sasha,

    I have noticed a quite massive memory leak when I register to a WMI event such as described in Wes Blog:
    http://weblogs.asp.net/whaggard/archive/2006/02/11/438006.aspx

    At first glance it seems like a pure unmanaged memory leak (I did compare the private byte vs GC heap counter) but that is not the whole story. When I dispose the event instance (e.NewEvent.Dispose();) it gets better but it is still big (~1MB per minute). Are you aware of this issue and do you know any workarounds for this issue?

    Yours,
    Alois Kraus

    Reply
  2. Sasha GoldshteinAugust 9, 2008 ב 6:03 AM

    I am not aware of the issue, but to eliminate the possibility that it’s a WMI leak I would try reproducing this in VBScript or C++. If the leak doesn’t occur, I suspect it could be a bug in the .NET WMI implementation (I’ve seen some).

    Reply
  3. overloofockMarch 11, 2009 ב 1:02 PM

    Greetings!

    Thought I’d share this. I have had problems with my internet connection at home for a while. I have the wireless router access point installed on the 1st floor and my computer is on the 2nd floor.

    It was really annoying that my internet connection would drop 4-5 times a day. The signal strength often shows “weak.”

    I did not know what to do until I came across this Wifi Signal Booster

    It solved all my network connection problem as soon as I had it installed! Now my signal shows “excellent” most of the time. So if you have a wifi signal/connection problem, this thing is going to solve your problem!

    Reply
  4. jeff andersonApril 7, 2009 ב 7:28 PM

    Sasha,

    I have been unable expose read/write properties in a WCF Instrumentation class. I also tried publishing a ManagamentEntity instance from a WCF assembly and that didn’t work either. Do you know if it’s possible?

    thanks

    Reply