Introduction
This article shall describe an approach to using Windows Management Instrumentation (WMI) calls to obtain system information. As you'll see, obtaining information from WMI based calls is trivial; it seems the hardest part of doing it at all is finding out what is available from within WMI. Fortunately, Microsoft provides some tools which also make WMI discovery pretty simple too.
Figure 1: Using WMI Calls to Obtain System Information.
Microsoft WMI Code Creator
The Microsoft WMI Code Creator application is available for free from Microsoft; it may be downloaded from this URL:
http://www.microsoft.com/downloads/details.aspx?FamilyID=2cc30a64-ea15-4661-8da4-55bbc145c30e&DisplayLang=en.
Per Microsoft, "The WMI Code Creator tool allows you to generate VBScript, C#, and VB .NET code that uses WMI to complete a management task such as querying for management data, executing a method from a WMI class, or receiving event notifications using WMI."
Figure 2: The WMI Code Creator Interface (Generating Code).
Getting Started
The solution contains a single project. The project is called "UsingWMI". The project is provided to demonstrate querying against and obtaining information from the WMI. Since there are literally hundreds of bits of information you can access through this interface, the demonstration only shows how to retrieve nineteen different things. The approaches shown in the first two methods used to access information through the WMI could be altered and used to access any of the information in the WMI. The project contains only a single form and this form contains all of the code necessary to perform the tasks described.
Figure 3: Solution Explorer with the Project Visible.
Code: Using WMI
This project is used to test different calls against the information exposed through the WMI interface. The project contains a single Windows form. The form contains a single textbox which is used to display the information gathered through a series of method calls.
The code for this form begins as follows:
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Management;
namespace UsingWMI
{
public partial class Form1 : Form
{
public Form1()
{
The class starts out with the default imports; I added System.Collections and System.Management to the defaults and dropped the generics. Following the namespace and class declaration, the forms load event executes all of the methods defined in the class and loads the results into the textbox for display:
public Form1()
{
InitializeComponent();
// Get System Information using WMI Calls
this.textBox1.Text += GetAccount() + Environment.NewLine;
this.textBox1.Text += Environment.NewLine;
this.textBox1.Text += GetHardDisks();
this.textBox1.Text += GetBoardMaker() + Environment.NewLine;
this.textBox1.Text += GetBoardSerNo() + Environment.NewLine;
this.textBox1.Text += GetBoardProductId() + Environment.NewLine;
this.textBox1.Text += Environment.NewLine;
this.textBox1.Text += GetCacheBlockSize() + Environment.NewLine;
this.textBox1.Text += GetCacheType() + Environment.NewLine;
this.textBox1.Text += GetCacheMaxSize() + Environment.NewLine;
this.textBox1.Text += Environment.NewLine;
this.textBox1.Text += GetCdRomDrive() + Environment.NewLine;
this.textBox1.Text += Environment.NewLine;
this.textBox1.Text += GetBIOSmaker() + Environment.NewLine;
this.textBox1.Text += GetBIOScaption() + Environment.NewLine;
this.textBox1.Text += GetBIOSserNo() + Environment.NewLine;
this.textBox1.Text += Environment.NewLine;
this.textBox1.Text += GetWinIconSpace() + Environment.NewLine;
this.textBox1.Text += GetWinCursorBlinkRate() +
Environment.NewLine;
this.textBox1.Text += GetWinScreenSaverActive() +
Environment.NewLine;
this.textBox1.Text += GetWinCoolSwitch() + Environment.NewLine;
this.textBox1.SelectionStart = textBox1.Text.Length;
}
The remaining code in the application is used to define the methods called during form load; in the following methods, there are examples of getting things such as the hard drive serial number, BIOS information, Windows Desktop information, and user information:
public string GetHardDisks()
{
ManagementObjectSearcher searcher = new
ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_LogicalDisk");
StringBuilder sb = new StringBuilder();
foreach (ManagementObject wmi in searcher.Get())
{
try
{
sb.Append("Drive Device ID: " +
wmi.GetPropertyValue("DeviceID").ToString() +Environment.NewLine);
sb.Append("Caption: " + wmi.GetPropertyValue("Caption").ToString() + Environment.NewLine);
sb.Append("Volume Serial Number: " + wmi.GetPropertyValue("VolumeSerialNumber").ToString()
+ Environment.NewLine);
sb.Append("Free Space: " + wmi.GetPropertyValue("FreeSpace").ToString() + "
bytes free" + Environment.NewLine + Environment.NewLine);
}
catch
{
return sb.ToString();
}
}
return sb.ToString();
}
public string GetBoardMaker()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_BaseBoard");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return Environment.NewLine + "Board Maker: " + wmi.GetPropertyValue("Manufacturer").ToString();
}
catch { }
}
return "Board Maker: Unknown";
}
public string GetBoardSerNo()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_BaseBoard");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "Serial Number: " + wmi.GetPropertyValue("SerialNumber").ToString();
}
catch { }
}
return "Serial Number: Unknown";
}
public string GetBoardProductId()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_BaseBoard");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "Product: " + wmi.GetPropertyValue("Product").ToString();
}
catch { }
}
return "Product: Unknown";
}
public string GetCacheBlockSize()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_CacheMemory");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "Cache Block Size: " + wmi.GetPropertyValue("BlockSize").ToString();
}
catch { }
}
return "Cache Block Size: Unknown";
}
public string GetCacheType()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_CacheMemory");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "Cache Type: " + wmi.GetPropertyValue("CacheType").ToString();
}
catch { }
}
return "Cache Type: Unknown";
}
public string GetCacheMaxSize()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_CacheMemory");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "Max Cache Size: " + wmi.GetPropertyValue("MaxCacheSize").ToString();
}
catch { }
}
return "Max Cache Size: Unknown";
}
public string GetCdRomDrive()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_CDROMDrive");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "CD ROM Drive Letter: " + wmi.GetPropertyValue("Drive").ToString();
}
catch { }
}
return "CD ROM Drive Letter: Unknown";
}
public string GetAccount()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_UserAccount");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "User Account Name: " + wmi.GetPropertyValue("Name").ToString();
}
catch { }
}
return "User Account Name: Unknown";
}
public string GetBIOScaption()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_BIOS");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "BIOS Caption: " + wmi.GetPropertyValue("Caption").ToString();
}
catch { }
}
return "BIOS Caption: Unknown";
}
public string GetBIOSmaker()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_BIOS");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "BIOS Maker: " + wmi.GetPropertyValue("Manufacturer").ToString();
}
catch { }
}
return "BIOS Maker: Unknown";
}
public string GetBIOSserNo()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_BIOS");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "BIOS Serial Number: " + wmi.GetPropertyValue("SerialNumber").ToString();
}
catch { }
}
return "BIOS Serial Number: Unknown";
}
public string GetWinIconSpace()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_Desktop");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "Desktop Icon Spacing: " + wmi.GetPropertyValue("IconSpacing").ToString();
}
catch { }
}
return "Desktop Icon Spacing: Unknown";
}
public string GetWinCursorBlinkRate()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_Desktop");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "Cursor Blink Rate: " + wmi.GetPropertyValue("CursorBlinkRate").ToString();
}
catch { }
}
return "Cursor Blink Rate: Unknown";
}
public string GetWinScreenSaverActive()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_Desktop");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "Screen Saver Active: " + wmi.GetPropertyValue("ScreenSaverActive").ToString();
}
catch { }
}
return "Screen Saver Active: Unknown";
}
public string GetWinCoolSwitch()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM
Win32_Desktop");
foreach (ManagementObject wmi in searcher.Get())
{
try
{
return "CoolSwitch: " + wmi.GetPropertyValue("CoolSwitch").ToString();
}
catch { }
}
return "CoolSwitch: Unknown";
}
Taking any of the methods shown, if one were to swap the table name in the select statement for a different option, and then swap out the property value, the same code could be used to gather any information from the WMI. Some of the data returned from the requests is recovered as arrays; in those cases you'd need to loop through the array to capture the individual values returned. The management searcher object accepts two arguments, one is called the management scope (e.g., "root\\CIMV2", and the other is called the object query which is defined as a simple SELECT statement.
Summary.
This article was intended to demonstrate an easy approach to obtain information from the WMI. If one needed information regarding the hardware (such as the serial number of a hard drive or board) or information about the desktop, this is easy way to collect it. The use of the Microsoft Code Creator tool really simplies the process of examining the options and toying with the results.