Posts
10
Comments
38
Trackbacks
0
Using WMI with C#

Recently I discovered the WMI (Windows Management Instrumentation) and was stunned at what it can do. Granted, the discovery was completely by accident, but I found it none the less. The WMI can mistify a lot of developers, especially new ones, so granted I was a little nervous and leery when I dove further into it, but what I found is that it can be an invaluable tool.

I jumped into learning the System.Management Namespace (which is where the WMI resides by the way) and discovered that WMI can save a developer tons of research time, clock cycles (as it is faster than other methods) and hair (from pulling it out looking for a solution).  

When developing Windows applications, developers often need information a system, either local or remote, that although commonplace, can be very tough to get. There is using the remote registry, but I myself do not allow remote registry access as do many network admins. WMI is usually wide open on networks, assuming you have the privelidges necessary to query it, just as it is with remote registry querying/editing.

There is another reason WMI appeals to so many developers nowadays, its called WQL (Windows Query Language). WQL allows us a developers to query WMI providers using a SQL-like query language. If you know the provider classes and the fields available, then you can get the info very easily. Lets say, for instance, that you wanted to see the capacity, used space and free space available on a CD-ROM, you WQL query would look like:

"select * from Win32_LogicalDisk WHERE DriveType = 5"

 

You can then take that query, plug it into a ManagementObjectSearcher (a member of the System.Management Namespace), then use that to retrieve that particular information. In my example I populate the returned data into a Generic Dictionary<string,string>  list, you may chose to do otherwise. But to retrieve the information I spoke about earlier, here is how you would find that information about the CD-Row:

 

 

public Dictionary<string, string> GetDriveInfo()
{
    //dictionary object to hold the values
    Dictionary<string, string> driveInfo = new Dictionary<string, string>();
    //create our WMI searcher
    ManagementObjectSearcher searcher = new ManagementObjectSearcher(@"select * from Win32_LogicalDisk WHERE DriveType = 5");
    //now loop through all the item found with the query
    foreach (ManagementObject obj in searcher.Get())
    {
        //create the used space by subtracting the size from the free space
        double used = (double)obj["Size"] - (double)obj["FreeSpace"];
        //add all the items to the collection
        driveInfo.Add("FreeSpace", obj["FreeSpace"].ToString());
        driveInfo.Add("Capacity", obj["Capacity"].ToString());
        driveInfo.Add("UsedSpace", used.ToString());
    }
    //return the info
    return driveInfo;
}
Notice how simple that was, and how ordinary it looks, it almost looks like you're querying a Database, but in fact you're querying a computer, either the system the application is running on, or a remote machine you have access to.
MSDN has a great writeup on WQL, what the DriveType values are you see me using in my queries, so dont let this scare you off, in the long run it will be quite the time saver when developing applications. Lets say you need to know how much free space is available on a network drive, before WMI and WQL you would have to rely on trying a remote registry query (testy at best, and it has to be open on the machine), but with WMI its a simple WQL query then a search.
The WQL Query for retrieving all network drives is:
 

"select name, FreeSpace from win32_logicaldisk where drivetype=4"

Notice I altered this query, unlike the first one I showed, in this one I only want to return the name of the network drive and the freespace it contains, I seen no need to return all the information if all I really wanted was 2 pieces. That would be the equivilent of "SELECT * FROM Table_Name" when all you needed was the record ID's. Once again we will plug this query into a ManagementObjectSearcher, this time using a SelectQuery, another member of WQL and the System.Management Namespace:

 

In this example I chose to populate a HashTable with the data returned, you, as with before, may chose to do it in a different fashion:

 

 

 public Hashtable ReadFreeSpaceOnNetworkDrives()
        {
            //create Hashtable instance to hold our info
            Hashtable driveInfo = new Hashtable();
            //query the win32_logicaldisk for type 4 (Network drive)
            SelectQuery query = new SelectQuery("select name, FreeSpace from win32_logicaldisk where drivetype=4");
            //execute the query using WMI
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
            //loop through each drive found
            foreach (ManagementObject drive in searcher.Get())
            {
                //add the name & freespace to our hashtable
                driveInfo.Add("Drive", drive["name"]);
                driveInfo.Add("Space", drive["FreeSpace"]);
            }
            return driveInfo;
        }
So, as you can see the WMI can be an invaluable tool to learn, and in my opinion its worth the time to learn. WMI can save you time, it definately, as shown in the 2 methods, much simpler than trying a remote registry query, and I think as more and more developers discover and learn how to use WMI it will definately grow.
posted on Friday, January 25, 2008 7:10 AM Print
Comments
Gravatar
# re: Using WMI with C#
Naresh
6/8/2009 8:20 AM
Thanks for sharing .It's quite easy to understand.
Gravatar
# re: Using WMI with C#
Nef
7/31/2009 10:57 PM
Great example. I was having trouble reading other examples on the web as I'm trying to learn WMI and was was getting confused. In just two simple samples, you cleared a lot for me.

Thanks,
Gravatar
# re: Using WMI with C#
Chris
2/4/2010 8:10 PM
It really help me a lot. Thanks.
Gravatar
# re: Using WMI with C#
favio.ar
6/8/2010 6:50 AM
Thanks a lot! your article did really help me.
Gravatar
# re: Using WMI with C#
Durak Online
9/10/2010 1:58 PM
Good article, help me a lot. Thank you very much.
Gravatar
# re: Using WMI with C#
crohn's healing
10/17/2010 5:33 PM
This is a fantastic site..By using this site i improved a lot.Thank you very much....
Gravatar
# re: Using WMI with C#
The North Face Backpacks
10/17/2010 5:38 PM
I look forward to working with them in all of these projects.. Thank you..
Gravatar
# re: Using WMI with C#
Charles
1/13/2011 6:52 AM
When trying to read the “FreeSpace” casting it to a number (double) it always tells me that "When casting from a number, the value must be a number less than infinity". Same with the “Size” property. I’m fairly sure that my drives do not have an infinite amount of space.
Any idea why it’s doing this?
Gravatar
# re: Using WMI with C#
Charles
1/14/2011 2:04 AM
I found the answer on a website. I was using “(double)obj["Size"]” and that results in an error message about the number being cast has to be less than infinity. Using “Convert.ToInt64(obj["Size"])” does work.
Gravatar
# re: Using WMI with C#
Duc
1/29/2012 2:53 PM
That is interesting example. I am interested management system including network devices, host, and other devices supported SNMP, ICMP, ...
Gravatar
# re: Using WMI with C#
ram
3/1/2012 3:26 AM
i want to find the usb pendrive connected to my machine , i have the following code working on my machine, but it does not work on my machine, both are windows xp machine,please help FindRemovableDisks()
{
var removableDisks = new List<RemovableDisk>();
var searcher =
new ManagementObjectSearcher("select * from Win32_LogicalDisk where Description like 'Removable Disk'");

foreach (ManagementObject managementObject in searcher.Get())
{
string caption = string.Empty;
string deviceID = string.Empty;
long size = 0;

foreach (PropertyData propertyData in managementObject.Properties)
{
if (propertyData.Value != null )
{
switch (propertyData.Name)
{
case "Caption":
caption = propertyData.Value.ToString();
break;
case "DeviceID":
deviceID = propertyData.Value.ToString();
break;
case "Size":
size = Int64.Parse(propertyData.Value.ToString(), CultureInfo.InvariantCulture);
break;
}
}
}

removableDisks.Add(new RemovableDisk(deviceID, caption, size,0,"",0,caption,0));
}

return removableDisks;
}
Gravatar
# re: Using WMI with C#
Harsha
9/18/2012 5:23 PM
very useful.. thanks for sharing.
Gravatar
# re: Using WMI with C#
kavya
4/8/2014 8:47 PM
ya its nice...but explain briefly how a client can querying to server socket

Post Comment

Title *
Name *
Email
Comment *  
Verification