Browse DevX
Sign up for e-mail newsletters from DevX


Exploring WMI: Integrate WMI into the .NET Framework : Page 2

Once you learn how to integrate Windows Management Instrumentation (WMI) with the .NET Framework, you can utilize a completely new approach for managing system resources.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Important Classes from the System.Management Namespace
ManagementBaseObject is the base class for most of the management object classes. It contains basic elements of a management object like the ClassPath, Properties Collection, and SystemProperties Collection (e.g., the class name, server, and namespace; WMI system property names always begin with "__".). It also contains Get- and Set- methods for accessing the Properties and Qualifiers of a managed object.

The ManagementBaseObject class is derived from the class System.ComponentModel.Component, which provides the base implementation for the IComponent interface and enables object sharing between applications. Component is the base class for all components in the common language runtime (CLR), which marshal by reference. Component also is remotable and derives from MarshalByRefObject. It provides an implementation of IComponent. You can host a Component in any object that implements the IContainer interface, and can query and get services from its container.

The ManagementObject class represents a data management object, which is an instance of a management class from the Common Information Model. (Note the difference between a managed class, which represents an entity in the WMI Repository, and a .NET class, which represents the code for a .NET object.) ManagementObject is derived from ManagementBaseObject, therefore it allows access to the Properties and Qualifiers Collections. Additional information contained in this class are the Scope (where you are connected and which credentials are you using), the connection Options, and a few others. Some very interesting parts of the ManagementObject are the public methods Get, Put, and InvokeMethod, which you use to bind to the management object, to save changes, and to invoke methods of the object. You can also access associated management objects (e.g., users are associated with groups) with the two public methods GetRelated and GetRealtionship.

The ManagementObjectCollection represents different collections of WMI instances like management objects, namespaces, scopes, and query watcher. You use this class to enumerate instances of management classes. For example, one management class represents a Windows service but many instances of the class can exist. For each service installed on your machine, there is one management object of type Win32_Service. You will obtain this collection of running instances from your management class to obtain the details of all services installed on your machine.

The ManagementClass is derived from ManagementObject, and it represents a management class from the Common Information Model. You can use this class to obtain all instances of ManagementObjects in a ManagementObjectCollection by calling the GetInstances method or to create new instances by calling the CreateInstance Method. It also contains a property Methods, which gets or sets a collection of MethodData objects that represent the methods defined in the WMI class.

The System.Management namespace contains many more classes, but they are far beyond the scope of this article. For further information take a look at the MSDN Library.

Manage Windows Services with WMI
Now that you know about WMI and its implementation in the .NET Framework, you can write your first sample application. For this purpose, this article shows you how to write a simple Windows Service manager, similar to the one you'll find in the Management Console. The final application should look similar to the Figure 3 screenshot (just ignore the titlebar, it's not one of the default Windows XP schemes).

Figure 3: Screenshot of the Sample Application—A Service Browser

Application Layout
The base of your sample application will be a standard Windows Application project. The application will contain two classes: the main form class, which contains the form, all controls, and all event handlers, and a ServiceNode class, which is derived from the ListViewItem class. Each object of the class ServiceNode will represent one Service in the ListView, and it will also contain data that belong to the management object of the CIMV2 class Win32_Service. You can find a detailed description of the Win32_Service class in the help file from the Platform SDK.

Building the Windows Service Manager
UI Design
Start with the main form. Before adding new controls, change the following properties:

(Name) ServiceForm
Text Local Services

Add a MainMenu to the Form. Then add a menu item 'File' and the submenu items 'Refresh', Seperator, and 'Exit'. Then modify the following settings:

(Name) mMain
(Name) miFile
Text &File
(Name) miRefresh
Text &Refresh
Shortcut F5
(Name) miExit
Text E&xit
Shortcut AltF4

Now add the MainMenu mMain to the ServiceForm by setting the 'Menu' property.

Next, add a Toolbar to the application. You will use it instead of menu items to access the service commands. In a real world application, you'd probably add a menu, a toolbar, and a context menu for this purpose. The following table shows the properties of the toolbar and the toolbar buttons.

(Name) ServiceToolbar
Appearance Flat
ShowToolTips True
Buttons (Collection) (click [...] to access the buttons collection)
(Name) tbbResume
Text Resume
ToolTipText Resume Service
Tag Resume
(Name) tbbStart
Text Start
ToolTipText Start Service
Tag Start
(Name) tbbStop
Text Stop
ToolTipText Stop Service
Tag Stop
(Name) tbbPause
Text Pause
ToolTipText Pause Service
Tag Pause
(Name) tbbRestart
Text Restart
ToolTipText Restart Service
Tag Restart

Now you can add the last control to your application, a ListView. It will be designed as a detailed list containing the columns 'Name', 'Description', 'Status', 'Startup Type', and 'Log On As'. The following table shows the properties of the ListView.

(Name) lvServices
FullRowSelect True
GridLines True
View Details
HideSelection False
MultiSelect False
Dock Fill
Columns (Collection) (click [...] to access the columns collection)
(Name) colName
Text Name
Width 120
(Name) colDescription
Text Description
Width 120
(Name) colStatus
Text Status
Width 100
(Name) colStartup
Text Startup Type
Width 100
(Name) colLogOnAs
Text Log On As
Width 100

Congratulations! You have finished the UI design of your sample application. Now, build and start the program. Check if the interface looks similar to the screenshot. (See figure 3). (Without the services listed, you still need to code that part.)

The ServiceNode Class
Create a new class called 'ServiceNode' and add it to your project. Before you start typing code, you need to add the reference for the assembly System.Management.dll. It contains the namespace System.Management, which you will use in your class. Right click on the references node of the project in the solution explorer and select Add Reference... (see Figure 4).

Figure 4: Microsoft Visual Studio—Solution Explorer

In the resulting dialog (shown in Figure 5), select the .NET tab and find System.Management in the list. Add it to the list of selected assemblies by double clicking it. Click OK to close the dialog, and take a look at the References node in solution explorer to make sure that the reference has been added.

Figure 5: Microsoft Visual Studio—Add Reference Dialog

Now that you have added the necessary reference, you can start implementing the ServiceNode class.

First, you need to import all used namespaces: System for all the base classes, System.Management for WMI, and System.Windows.Forms for the ListViewItem class from which you want to derive your ServiceNode class:

using System; using System.Management; using System.Windows.Forms;

Next, add the derivation to your class definition and define an enumeration that will represent the possible service states. This enumeration is not very useful for your own ServiceNode class, but it can really help other coders who need to use your class. So for the sake of good code, add it:

namespace ServiceManager { public class ServiceNode : ListViewItem { public enum ServiceState { Start, Stop, Pause, Resume } } }

Now, you need a ManagementObject field in your class to store the reference to an instance of a Win32_Service management class. Just add it right at the beginning of your class:

protected ManagementObject mo = null;

With that finished, you can address the constructor for your class. You need a constructor that receives a management object and fills all the necessary parts of the derived ListViewItem. To achieve the highest possible code reuse, perform a little trick: create a property that represents your ManagementObject, and then, in the set part of the property code, transfer the values from the CIM to the ListViewItem. Having such a property in your class, you can create a very short constructor. Just assign the object you get in the constructor toy your property and you're done:

public ServiceNode(ManagementObject moService) { ServiceObject = moService; } public ManagementObject ServiceObject { get { return mo; } set { mo = value; if(mo!=null) { SubItems.Clear(); Text = (string)mo.Properties["Name"].Value; SubItems.Add((string)mo.Properties["Description"].Value); SubItems.Add((string)mo.Properties["State"].Value); SubItems.Add((string)mo.Properties["StartMode"].Value); SubItems.Add((string)mo.Properties["StartName"].Value); } } }

As you can see in this code, you use the Properties Collection from the ManagementObject class to access the various properties of the Win32_Service CIM class. Since the Value property of the Collection item is of type object, you need to cast it to a string to add it to the SubItems collection of your ListViewItem. You will add the ListViewItem itself to the ListView lvServices later.

To make your class more useable, add a few public properties that enable easy access to the object properties stored in the ListViewItem:

public string Name { get { return Text; } } public string Description { get { return SubItems[1].Text; } } public string State { get { return SubItems[2].Text; } } public string StartupType { get { return SubItems[3].Text; } } public string LogOnAs { get { return SubItems[4].Text; } } public bool CanPause { get { return (bool)mo.Properties["AcceptPause"].Value; } }

Although you could always use the management object, I decided to use the SubItems collection to access the desired information. However, nothing's stopping you from using the Properties collection of your management object.

The last parts of your ServiceNode class are two Methods: ChangeState and Refresh. You use the ChangeState method to call the InvokeMethod method on your management object to start, stop, pause, and resume the service. This call takes two parameters: the first is the name of the method to be called, and the second is an object array with the arguments for the call. Since your methods don't need any arguments, you can use null instead of the array.

The Refresh method is used to refresh the current ListViewItem. You could also use the Refresh method in your ServiceObject property. But I decided to implement this behavior separately so as not to unnecessarily obfuscate your code:

public void ChangeState(ServiceState newState) { switch(newState) { case ServiceState.Start: mo.InvokeMethod("StartService", null); break; case ServiceState.Stop: mo.InvokeMethod("StopService", null); break; case ServiceState.Pause: mo.InvokeMethod("PauseService", null); break; case ServiceState.Resume: mo.InvokeMethod("ResumeService", null); break; } } public void Refresh() { mo.Get(); SubItems.Clear(); Text = (string)mo.Properties["Name"].Value; SubItems.Add((string)mo.Properties["Description"].Value); SubItems.Add((string)mo.Properties["State"].Value); SubItems.Add((string)mo.Properties["StartMode"].Value); SubItems.Add((string)mo.Properties["StartName"].Value); }

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date