WMI Provider Extensions in .NET 3.5 - Read-Write and Method Provider
In the previous post in this series, we have looked into implementing a rudimentary WMI provider which exposes read-only information. In this post, we will make our provider more interesting by exposing read-write information.
Read-write information is exposed by defining a read-write property and decorating it with the [ManagementConfiguration] attribute. The [ManagementEntity], [ManagementBind] and [ManagementKey] requirements described in the previous post must still hold.
The following code demonstrates a WMI provider which exposes a read-write property controlling the brightness of the screen. For demonstration purposes, the code to modify screen brightness has been omitted from the sample.
[ManagementEntity]
public class BrightnessController
{
[ManagementBind]
public BrightnessController()
{
Id = 1; BrightnessLevel = 500;
}
[ManagementKey]
public int Id { get; private set; }
[ManagementConfiguration]
public int BrightnessLevel { get; set; }
}
Due to limitations in the current WMI Provider Extensions for .NET implementation, a singleton WMI provider cannot expose any updateable properties. Attempting to update a property exposed by a singleton WMI provider will result in an ExecutionEngineException at runtime.
The wmic tool has the capability of writing values to writeable properties of a WMI provider. The following command executed from a command prompt will modify the BrightnessLevel value depicted in the previous section.
wmic /namespace:\\root\MyApplication path BrightnessController.Id=1 set BrightnessLevel=400
Note the use of the .Id=1 syntax to specify which brightness controller instance we are updating. Alternatively, query syntax can also be used:
wmic /namespace:\\root\MyApplication path BrightnessController where Id=1 set BrightnessLevel=400
Modifying updateable information from managed code generated by Visual Studio is as easy as writing a value to a writeable property. After generating the managed class, the following code will update the brightness controller’s brightness level:
foreach (ROOT.MYAPPLICATION.BrightnessController
controller in
ROOT.MYAPPLICATION.BrightnessController.GetInstances(
"Id = 1"))
{
controller.BrightnessLevel = 400;
}
Control Methods
In the previous section, we have exposed read-write properties from a WMI provider. Setting a property value is similar to invoking a method; however, similarly to the semantic difference between properties and methods in .NET, there is a difference between properties and methods in the WMI taxonomy.
In this section, we will define a method exposed by our WMI provider by decorating it with the [ManagementTask] attribute. The [ManagementEntity], [ManagementBind] and [ManagementKey] requirements described in the previous post must still hold.
The following code demonstrates a WMI provider which exposes a PrintToConsole method which outputs the specified string to the console. This would clearly be a bad idea for an in-process provider (which has no console), but will work just fine for a decoupled provider hosted in a console application.
[ManagementEntity]
public class Printer
{
[ManagementBind]
public Printer([ManagementName("Id")] int id)
{
Id = id;
}
[ManagementKey]
public int Id;
[ManagementTask]
public void PrintToScreen(string s)
{
Console.WriteLine(s);
}
}
Due to limitations in the current WMI Provider Extensions for .NET implementation, a singleton WMI provider cannot expose any methods. Attempting to call a method exposed by a singleton WMI provider will result in an ExecutionEngineException at runtime.
The wmic tool has the capability of invoking methods exposed by a WMI provider. The following command executed from a command prompt will invoke the PrintToScreen method depicted in the previous section.
wmic /namespace:\\root\MyApplication path Printer.Id=1 call PrintToScreen Hello!
Invoking provider methods from managed code generated by Visual Studio is as easy as calling a method on an object. After generating the managed class, the following code will invoke the PrintToScreen method:
foreach (ROOT.MYAPPLICATION.Printer printer in
ROOT.MYAPPLICATION.Printer.GetInstances("Id = 2"))
{
printer.PrintToScreen("Hello!");
}
In the next (final) post in the series, we will look into publishing events from a WMI provider and briefly mention some advanced mechanisms.