Page 1 of 1

Using WMI Class in C#

#1 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1641
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Post icon  Posted 10 February 2008 - 10:21 PM

Welcome to my tutorial on Using WMI in C#. In this tutorial we will discuss using Windows Management Instrumentation, or WMI. Windows Management Instrumentation (WMI) is the infrastructure for management data and operations on Windows-based operating systems. With WMI you can get information on all hardware in a system, including:
  • HDD Serial Number(s)
  • HDD Sizes
  • HDD Free Space
  • CPU Serial Number(s)
  • CPU Clock Speed
  • CPU Socket Type
  • Network Adapter MAC Address
  • Network Adapter Default Gateway


And much more. In this tutorial we will be looking at some of the information that can be retrieved using WMI, along with Windows Query Language, or WQL. though this tutorial isn't an all inclusive tutorial on the topic, we will look at enough to at least give you a good foundation for using WMI in your applications.

In this tutorial we will see how to retrieve HDD information, CPU information, and Network Adapter information. For this tutorial there are 3 classes we will be using to retrieve this information for our applications:



Of course there are many more WMI Classes that are available, and if I were to try and cover all of them this would be a 20 page tutorial. All the items we will be using require a reference to the System.Management Namsepace provided in the .Net framework

Win32_LogicalDiskClass

The Win32_LogicalDisk WMI class represents a data source that resolves to an actual local storage device on a computer system running Windows. In this section we will do a few tasks such as:

  • Retrieve selected HDD serial number
  • Retrieve selected HDD free space
  • Retrieve HDD initial size

The first task, getting the serial number of a selected HDD (as with all the tasks in this section) we will be passing a drive letter to our method, with that drive letter we will query the system using the DeviceID Property of the Win32_LogicalDisk class. Once we have done that we have access to many properties, which we will use in this section. First, to receive the serial number:


/// <summary>
/// method to retrieve the selected HDD's serial number
/// </summary>
/// <param name="strDriveLetter">Drive letter to retrieve serial number for</param>
/// <returns>the HDD's serial number</returns>
public string GetHDDSerialNumber(string drive)
{
	//check to see if the user provided a drive letter
	//if not default it to "C"
	if (drive == "" || drive == null)
	{
		drive = "C";
	}
	//create our ManagementObject, passing it the drive letter to the
	//DevideID using WQL
	ManagementObject disk = new ManagementObject("Win32_LogicalDisk.DeviceID=\"" + drive + ":\"");
	//bind our management object
	disk.Get();
	//return the serial number
	return disk["VolumeSerialNumber"].ToString();
}



As you can see, we check the DevideID to ensure we are looking at the proper HDD, then we use the Get Method of the ManagementObject Class to bind our management object, allowing us to retrieve the attributes we are looking for.

The nice thing about the Win32_LogicalDisk Class is once you learn to retrieve one attribute or property, the rest are easily retrieved, such as retrieving the free space of a HDD:


/// <summary>
/// method to retrieve the HDD's freespace
/// </summary>
/// <param name="drive">Drive letter to get free space from (optional)</param>
/// <returns>The free space of the selected HDD</returns>
public double GetHDDFreeSpace(string drive)
{
	//check to see if the user provided a drive letter
	//if not default it to "C"
	if (drive == "" || drive == null)
	{
		drive = "C";
	}
	//create our ManagementObject, passing it the drive letter to the
	//DevideID using WQL
	ManagementObject disk = new ManagementObject("Win32_LogicalDisk.DeviceID=\"" + drive + ":\"");
	//bind our management object
	disk.Get();
	//return the free space amount
	return Convert.ToDouble(disk["FreeSpace"]);
}




And retrieving the initial size of a selected HDD, like so:


/// <summary>
/// method to retrieve the HDD's size
/// </summary>
/// <param name="drive">Drive letter to get free space from (optional)</param>
/// <returns>The free space of the selected HDD</returns>
public double getHDDSize(string drive)
{
	//check to see if the user provided a drive letter
	//if not default it to "C"
	if (drive == "" || drive == null)
	{
		drive = "C";
	}
	//create our ManagementObject, passing it the drive letter to the
	//DevideID using WQL
	ManagementObject disk = new ManagementObject("Win32_LogicalDisk.DeviceID=\"" + drive + ":\"");
	//bind our management object
	disk.Get();
	//return the HDD's initial size
	return Convert.ToDouble(disk["Size"]);
}




You will notice in the previous 3 methods the drive letter is actually optional. We check to see if a drive was provided, and if it wasnt then we default it to the users "C" drive, which is usually the OS drive on most computers.


Win32_NetworkAdapterConfiguration Class

The Win32_NetworkAdapterConfiguration WMI class represents the attributes and behaviors of a network adapter. This class includes extra properties and methods that support the management of the TCP/IP and IPX (Internetwork Packet Exchange) protocols.

With this class we can get information such as:

  • MAC Address
  • Default IP Gateway
  • IP Enabled Status


In the following examples we will be introduced to the ManagementObjectCollection Class. This class represents different collections of management objects that can be retrieved through WMI. We will then loop through all the items in our collection to retrieve information about the network adapter on that particular system.

First we will look at how to retrieve the systems MAC address. In these examples we will onl;y be retrieving information from the first network adapter we find, they can easily be modified to create a collection of network adapter information.


/// <summary>
/// Returns MAC Address from first Network Card in Computer
/// </summary>
/// <returns>MAC Address in string format</returns>
public string FindMACAddress()
{
	//create out management class object using the
	//Win32_NetworkAdapterConfiguration class to get the attributes
	//of the network adapter
	ManagementClass mgmt = new ManagementClass("Win32_NetworkAdapterConfiguration");
	//create our ManagementObjectCollection to get the attributes with
	ManagementObjectCollection objCol = mgmt.GetInstances();
	string address = String.Empty;
	//loop through all the objects we find
	foreach (ManagementObject obj in objCol)
	{
		if (address == String.Empty)  // only return MAC Address from first card
		{
			//grab the value from the first network adapter we find
			//you can change the string to an array and get all
			//network adapters found as well
			//check to see if the adapter's IPEnabled
			//equals true
			if ((bool)obj["IPEnabled"] == true)
			{
				address = obj["MacAddress"].ToString();
			}
		}
		//dispose of our object
		obj.Dispose();
	}
	//replace the ":" with an empty space, this could also
	//be removed if you wish
	address = address.Replace(":", "");
	//return the mac address
	return address;
}




In the first example, along with the others in this section, we will be using the GetInstances Method of the ManagementObjectCollection Class to retrieve all instances of the specified class, in this case the Win32_NetworkAdapterConfiguration class.

Now lets look at retrieving the default IP gateway of a network adapter. As with the first example, we will be using the first adapter we find, as long as its IPEnabled Property is true:


/// <summary>
/// method to retrieve the network adapters
/// default IP gateway using WMI
/// </summary>
/// <returns>adapters default IP gateway</returns>
public string GetDefaultIPGateway()
{
	//create out management class object using the
	//Win32_NetworkAdapterConfiguration class to get the attributes
	//of the network adapter
	ManagementClass mgmt = new ManagementClass("Win32_NetworkAdapterConfiguration");
	//create our ManagementObjectCollection to get the attributes with
	ManagementObjectCollection objCol = mgmt.GetInstances();
	string gateway = String.Empty;
	//loop through all the objects we find
	foreach (ManagementObject obj in objCol)
	{
		if (gateway == String.Empty)  // only return MAC Address from first card
		{
			//grab the value from the first network adapter we find
			//you can change the string to an array and get all
			//network adapters found as well
			//check to see if the adapter's IPEnabled
			//equals true
			if ((bool)obj["IPEnabled"] == true)
			{
				gateway = obj["DefaultIPGateway"].ToString();
			}
		}
		//dispose of our object
		obj.Dispose();
	}
	//replace the ":" with an empty space, this could also
	//be removed if you wish
	gateway = gateway.Replace(":", "");
	//return the mac address
	return gateway;
}




Win32_Processor

This class allows us to retrieve properties of the processor running on a Windows based computer. On a system with multiple processors, one instance of the Win32_Processor class exists for each processor. Using this class allows us to retrieve information about the processor such as:

  • CPU ID
  • CPU Manufacturer
  • CPU Status
  • CPU Current Clock Speed


As with the other class examples, we will only be getting information from the first processor we find, they too can be modified to return information for all processors in a system. In these examples we will also be using the GetInstances Method, as each processor will have it's own instance. First, getting the CPU ID:


/// <summary>
/// Return processorId from first CPU in machine
/// </summary>
/// <returns>[string] ProcessorId</returns>
public string GetCPUId()
{
	string cpuInfo =  String.Empty;			
	//create an instance of the Managemnet class with the
	//Win32_Processor class
	ManagementClass mgmt = new ManagementClass("Win32_Processor");
	//create a ManagementObjectCollection to loop through
	ManagementObjectCollection objCol = mgmt.GetInstances();
	//start our loop for all processors found
	foreach(ManagementObject obj in objCol)
	{
		if(cpuInfo == String.Empty) 
		{
			// only return cpuInfo from first CPU
			cpuInfo = obj.Properties["ProcessorId"].Value.ToString();
		}			 
	}
	return cpuInfo;		
}




To get the manufacturer, we will return the Manufacturer property of the first instance we find:


/// <summary>
/// method for retrieving the CPU Manufacturer
/// using the WMI class
/// </summary>
/// <returns>CPU Manufacturer</returns>
public string GetCPUManufacturer()
{
	string cpuMan = String.Empty;
	//create an instance of the Managemnet class with the
	//Win32_Processor class
	ManagementClass mgmt = new ManagementClass("Win32_Processor");
	//create a ManagementObjectCollection to loop through
	ManagementObjectCollection objCol = mgmt.GetInstances();
	//start our loop for all processors found
	foreach (ManagementObject obj in objCol)
	{
		if (cpuMan == String.Empty)
		{
			// only return manufacturer from first CPU
			cpuMan = obj.Properties["Manufacturer"].Value.ToString();
		}
	}
	return cpuMan;		
}




Processors today are vastly different than they were 20 years ago, today people are over clocking their processors to get more power out of them. That being the case, some systems might be running at a higher clock speed than what is listed on the system information, so we will use the CurrentClockSpeed Property to retrieve the current clock speed of the first instance we find:


/// <summary>
/// method to retrieve the CPU's current
/// clock speed using the WMI class
/// </summary>
/// <returns>Clock speed</returns>
public int GetCPUCurrentClockSpeed()
{
	int cpuClockSpeed = 0;
	//create an instance of the Managemnet class with the
	//Win32_Processor class
	ManagementClass mgmt = new ManagementClass("Win32_Processor");
	//create a ManagementObjectCollection to loop through
	ManagementObjectCollection objCol = mgmt.GetInstances();
	//start our loop for all processors found
	foreach (ManagementObject obj in objCol)
	{
		if (cpuClockSpeed == 0)
		{
			// only return cpuStatus from first CPU
			cpuClockSpeed = Convert.ToInt32(obj.Properties["CurrentClockSpeed"].Value.ToString());
		}
	}
	//return the status
	return cpuClockSpeed;	
}




As stated before this isnt an all exhaustive list of classes and ways to use the WMI class, there are hundreds (maybe more) items that can be retrieved about a system using this class. The items in this tutorial, and the attached class file, will give you a good jump start on using the WMI class in your applications.

I will be including the class file I created for this tutorial, the class itself is under the GNU General Public License, meaning you can modify and distribute it as you see fit, but the license information must remain intact. I hope you found this tutorial useful and informative, and thank you for reading.

Happy Coding!
Attached File  PC_WMI.zip (13K)
Number of downloads: 5541

Is This A Good Question/Topic? 0
  • +

Replies To: Using WMI Class in C#

#2 Guest_kpo*


Reputation:

Posted 08 July 2010 - 08:34 AM

Hey Richard... thanks for your post... I am able to get info using the WMI classes, but when I try to update a property, the update is not occurring. No error is thrown, but the update is not happening.

My goal is to check the Startup Type for a specific service... if it is not set to Automatic, then set it to Automatic. Have you ever worked with updating properties via WMI?

Thanks for any help you might provide.


            ManagementObjectSearcher mgmtSearcher = new ManagementObjectSearcher(new SelectQuery("Win32_Service"));
            ManagementObjectCollection mgmtCollection = mgmtSearcher.Get();

            foreach (ManagementObject obj in mgmtCollection)
            {

if (obj["name"].ToString().ToLower() == "carboncopy32" && obj["StartMode"].ToString().ToLower() != "automatic")
                {
                    
                    object value = "Automatic";
                    obj.SetPropertyValue("StartMode", value);

                    //obj.Properties["StartMode"].Value = "Automatic";
                   

                }
}


Was This Post Helpful? 0

#3 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1641
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Posted 08 July 2010 - 08:36 AM

If you're looking to change the status of a Windows service you might want to go a different route than WMI, take a look at this for an idea
Was This Post Helpful? 0
  • +
  • -

#4 Guest_kpo*


Reputation:

Posted 08 July 2010 - 08:48 AM

View PostPsychoCoder, on 08 July 2010 - 07:36 AM, said:

If you're looking to change the status of a Windows service you might want to go a different route than WMI, take a look at this for an idea


That is beautiful... thanks!
Was This Post Helpful? 0

#5 Guest_Duncan*


Reputation:

Posted 11 August 2010 - 07:20 AM

Hi Richard - thanks for the post

However..

I'm having a problem with the GetHDDSerialNumber method whereby it gets to the disk.Get() line and then hangs for 5 minutes before erroring out with a System.Runtime.InteropServices.COMException. The partial stack trace is

at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
at System.Management.ManagementObject.Get()

What could be causing it to hang then error like that? What is it trying to do with that Get() method? Any pointers greatly appreciated.

Duncan
Was This Post Helpful? 0

#6 Guest_Anurag*


Reputation:

Posted 19 August 2010 - 11:47 PM

Hi I am accessing some computer systems details but I get ACCESS DENIED error. When I added my account on one of those remote server in administrators then i get the details of that server with no error. Is there any other option without adding my account to administrator on that particular machine and still access the remote system's details?
How can I access remote system's details using ports?
Was This Post Helpful? 0

#7 Guest_Guna*


Reputation:

Posted 23 August 2010 - 10:20 PM

Thx... g8 post!!
Was This Post Helpful? 0

#8 a2kat  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 08-September 10

Posted 16 September 2010 - 03:56 AM

Thank you for this owesome tutorial, but it doesn't work for me. Why it can be?
Posted Image
Thank you! :chinese:

This post has been edited by a2kat: 16 September 2010 - 03:57 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1