Introduction
WMI is a powerful technology widely used by programmers to manage computers. It can be accessed in .NET through the System.Management
namespace. Although WMI classes are highly structured, the common way to use it is through WQL requests returning variant objects. The purpose of the WMIwrapper project in this article is to provide classes equivalent to WMI ones provided in the root\CIMV2
namespace. It implements many classes with their properties and methods, so that the programmer will not rely on WQL strings (such as SELECT * FROM Win32_LogicalDisk
) that cannot be verified at compilation, but will use Intellisense in the Visual Studio GUI to get objects, properties, and methods.
The demo application is a quick and dirty proof of concept. First, connect to a computer with the File / Open menu ("." is the default value for the local computer) and navigate in the tree of objects (not all classes are included, refer to the help file for a complete reference). The right pane of the screen displays all the properties and their values returned by the native WMI class for the first instance found. The bottom of the screen displays a gridview with all the properties (arrays excluded) of the corresponding wrapper's class, one instance per line (for example, one line for each drive). Comparing the panels is a quick and efficient way to debug the wrapper.
Background
The base class is WMIobject
. It does not exist in native WMI, but is used to provide general methods, mainly used to convert WMI types to .NET types and implement WMI methods. Other classes inherit from it, following the WMI architecture. For example (":" means "inherits from"), Win32_ComputerSystem
: CIM_UnitaryComputerSystem
: CIM_ComputerSystem
: CIM_System
: CIM_LogicalElement
: CIM_ManagedSystemElement
: WMIobject
. Each class implements a part of the properties and methods used by the final one. As a rule of thumb, only the Win32-prefixed classes will be used outside the project.
The huge number of classes does not allow including a diagram in this article. You may use the Documentation.chm file, or create a class diagram to see the hierarchy of classes. The actual hierarchy of WMI classes has been respected, with minor adaptations, because WMI supports multiple inheritance, but .NET does not.
Classes go by two: each object class, say CIM_System
, has its corresponding collection class with the same name and a final s (CIM_Systems
). The collections mainly provide properties to find an item: the most common way to query WMI consists of filling the collection and then enumerating the items.
I added an extra class called Computer
to simplify access to the other classes. Its use is detailed below.
Using the code
Computer hardware and system
The simplest use of the wrapper is through the Computer
class. Connect to a computer with this code:
Dim ComputerName As String = "."
Dim _Computer As New WMIwrapper.Computer(ComputerName)
Your Windows account must have the necessary privileges to connect to a remote computer: either you are an administrator in a domain, or you have an account with the same login and password on both computers in a workgroup.
Since loading and running WMI takes quite a long time (usually a second or two), queries are not run by default. You must use methods to to this. The following code queries Win32_Processors
:
_Computer.GetLogicalElements(WMIwrapper.Computer.LogicalElements.Processors)
Now, the Processors
property contains a collection of Processor
objects. Loop through it to read their properties, such as Caption
:
If _Computer.Processors IsNot Nothing Then
For Each Win32_Processor As WMIwrapper.Win32_Processor In _Computer.Processors
MsgBox(Win32_Processor.Caption)
Next
End If
Refer to Documentation.chm to discover all the methods and properties of the Computer
class.
File shares
Computer
methods allow managing file shares (this is not so easy with .NET):
GetShares
fills the Shares
property, a collection of Share
objects. Each of them is a file or printer share on the computer, supporting properties such as Path
or AccessMask
and methods such as Delete
.CreateFileShare
, DeleteFileShare
allow creating or deleting file shares without calling GetShares
.
Computer control
Reboot
and Shutdown
methods are available. GetOperatingSystem
must have been called before.
Using the Win32 classes
Full WMI access is possible if you use the Win32-prefixed classes. Generally, you will fill a collection and then loop through it:
Dim _Processors As New WMIwrapper.Win32_Processors(ComputerName)
If _Processors IsNot Nothing Then
For Each Win32_ProcessorI As WMIwrapper.Win32_Processor In _Processors
MsgBox(Win32_ProcessorI.Caption)
Next
End If
The collection constructor allows using the key values of the classes to select a single item, or to pass a WQL condition:
Dim _Shares As New WMIwrapper.Win32_Shares(ComputerName,"Admin$")
If _Shares IsNot Nothing Then
For Each Win32_ShareI As WMIwrapper.Win32_Share In _Shares
MsgBox(Win32_ShareI.Path)
Next
End If
Dim _Volumes As New WMIwrapper.Win32_Volumes(ComputerName, , "Caption = 'C:\\'")
If _Volumes IsNot Nothing Then
For Each Win32_VolumeI As WMIwrapper.Win32_Volume In _Volumes
MsgBox(Win32_VolumeI.DeviceID)
Next
End If
A few classes are used differently. Security classes (Win32_ACE
, Win32_SecurityDescriptor
, and Win32_Trustee
) do not belong to collections, and can be created from scratch. See the code of the CreateFileShare
function in Computer.vb to understand how to use them.
Methods are implemented. They return an InvokeError
object, with two properties: Number
(0 for success) and Message
.
Points of interest
Similar code can be obtained using MgmtClassGen.exe with less effort, but this tool generates a class for each WMI class, including all the necessary code. If you have an intensive use of WMI, you get a lot of redundant code, which should be put in base classes. That's what WMIwrapper
does.
EasyWMI is a similar project, developed in parallel. WMIwrapper
is just closer to the original WMI architecture, so I hope it will be easier to maintain in the future. I think it is easier to use because the documentation has been the object of all efforts.
Acknowledgements
I used TechNet as a reference for classes. Microsoft's WMI tools, especially WMI CIM Studio is the most convenient way to understand inheritance.
I used Sandcastle to compile the help file, through Sandcastle help file builder GUI.
History
This is an endless project because some classes are still missing and WMI evolves with new versions of Windows. You may find a few 'TODO
comments in the code for non essential methods (I do not think WMI is the best way to create a folder, for example), I will fill them when I have time. Anyway, future versions are planned.
- Version 1.0: first public version.