One way of obtaining management data and operation related to the Windows operating system is to use the Windows Management Instrumentation (WMI) classes. WMI can be considered as a database while the classes are like tables in the database. Therefore WMI can be queried to obtain specific table/class information.
To use WMI classes in .NET one has to use the System.Management library. In Visual Studio the library needs to be added to the references.
Initial Notes:
- WMI can be used to obtain operation information from a remote Windows machine. However, this article only describes how to connect and use the WMI on the local machine.
- WMI is a Windows service that can be switched off at any time from the Service console. However, this is not recommended as most applications depend on the service to run properly.
Step 1: Connecting to WMI
To open a connection with WMI the location of the WMI database that is to be used need to be obtained. To connect with the local WMI the standard path is
\\localhost\root\cimv2
In .NET, the class ManagementScope is used to define the WMI instance on which operations will be executed.
ManagementScope scope = new ManagementScope(@"\\localhost\root\cimv2", new ConnectionOptions());
scope.Connect();
Once the connect command is issued it is best to check if the connection was established or not. To do this the IsConnected() method is invoked on the ManagementScope instance.
if (scope.IsConnected)
{
// Work with WMI scope
}
Step 2: Query WMI
Once the WMI connection is established data can be retrieved. For the purpose of this article the Win32_DiskDrive class will be queried. Win32_DiskDrive contains information about the disk drives installed on the machine as seen by the Windows operating system.
// 1. Create the query
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_DiskDrive");
// 2. Create a WMI searcher, i.e. a class capable of performing queries on the WMI scope used in the application.
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
// 3. Retrieve the information
ManagementObjectCollection queryCollection = searcher.Get();
Step 3: Reading the retrieved data
The data returned by the WMI query in the collection can be read by converting the collection returned into an enumerator and iterating on the records.
ManagementObjectCollection.ManagementObjectEnumerator enumerator = queryCollection.GetEnumerator();
while (enumerator.MoveNext())
{
ManagementBaseObject diskDrive = enumerator.Current;
}
To access the columns in the diskDrive instance the index operator ([]) can be used with the column name. For example to read the size of a sector in bytes,
object bytesPerSectorRaw = diskDrive["BytesPerSector"];
uint bytesPerSecotr = 0;
if (bytesPerSectorRaw != null && uint.TryParse(bytesPerSectorRaw.ToString(), out bytesPerSecotr))
{
}
Final Note
WMI data types match directly into .NET data types except for the DateTime structure. In WMI DateTime is stored as a floating number which cannot be type casted into the .NET DateTime structure. However .NET provides a special method ManagementDateTimeConverter.ToDateTime() that given the WMI DateTime value converts it into the equivalent .NET DateTime structure.