IT Training Courses
Microsoft Gold IT Training Partner
800-326-1044
IT Training Newsletters WMI for .NET programmers

WMI for .NET programmers

...in other words, how to get computer-specific information in .NET.

by Mike Bailey
SQLSoft+ Senior Instructor, MCT, MCSD

Ever wonder what computer information you can read with .NET? The answer is a lot! Both hardware information (such as NICs, drives, motherboards) and software information (services, products installed, processes running) are easy to retrieve with your new best friend, System.Management.

System.Management is the namespace thatcontains the tools to use WMI (Windows Management Instrument). WMI is a flexible tool for working with a computer that has a database full of classes. When we ask for data from WMI, it will look in the database and figure out how to contact (via some COM component) whatever it is we want.

The whole idea of WMI is not to have the classes set in stone. One computer may have many more classes than another. Each new version of Windows has more classes than the last. A computer with SMS or SQL Server or even just some hardware upgrade may have new classes added to it.

Adding a Reference

Anyway, let's make WMI work for us. System.Management is not referenced by default in any of the Visual Studio project templates so we must do it ourselves. To keep things simple, let's do all our testing in a VB.NET or C# Windows Application. To add a reference just right click the references in the solution explorer and choose add reference. System.Management is under the .NET tab since it is part of the .NET framework.

Adding a reference to System.Management:

There are a lot of classes in System.Management so let's look at just the ones we will use in this article:

ManagementClass Represents a class, not an object. This is for finding out what a classes properties are or making a new object.(example, the Win32_Process class)

ManagementObject

An object of a class (example, the Win32_Process object with ProcessId=1120)
PropertyData A property item of a class
ObjectQuery A SQL query
ManagementObjectSearcher Actually runs a query
ManagementScope Sets the computer and namespace
ManagementBaseObject A generic class we use for parameters to methods

Procedure 1, Listing all the instances of a class

What services are on my machine? Let's take the class and find all the instances available. The class is called Win32_Service and it has a Name and State Property.

First we create the ManagementClass using the class name (oServices), then we ask the class to GetInstances. As we loop through each instance (oService), we can see the Name and State.

NOTE: All the code examples write their results to a ListBox called lstData. To run the code, build a Windows Application with a ListBox called lstData, add a button, and put this code behind the button's click event. The entire code can be downloaded for free if you have an account on My SQLSoft. (Accounts can be created free.)

VB.NET

C#

Procedure 2, What properties does a class have?

We will use the Microsoft tools to really see what is out there later but for now let's ask a class what it can do for us. The following code will list the properties of a class.

VB.NET

C#

Now that we are pros with WMI, we just go back to our friend the ManagementClass (oService), then we just loop through the properties (PropertyData). We don't have to actually connect to any particular service (like Alerter , Browser,etc) , just the class in general.

Procedure 3, SQL

Why can't I just write a SQL statement for the data I want? You can! Now don't go crazy with unions, cubes, or even joins, but you can use the basic SQL SELECT statement. One more problem, the LIKE operator doesn't work in Windows 2000 and earlier.

SELECT propertyname, propertyname FROM class WHERE criteria

Example:

Need BIOS info?

SELECT Name, SerialNumber FROM WIN32_BIOS

Need to know how many Solitaires we are playing?

SELECT * FROM win32_Process WHERE name='sol.exe'

This is really the preferred way to get data because we can ask for just the properties we care about and also we can be very specific about what we want. This is very handy when looking for an event log entry from a specific program with out having to sort through everything in the log.

Only log entries from Norton AntiVirus.

SELECT * FROM win32_NTLogEvent WHERE Logfile='Application' AND SourceName Like 'Norton%'

Just like in SQL, the asterisk means return all fields. Some classes in WMI have a lot of properties, so it saves bandwidth to only ask for the fields you use.

VB.NET

C#

In this example, we followed these simple steps:

  1. Built the string of the SQL (sSQL).
  2. Create a ObjectQuery(oQuery) object holds the SQL.
  3. Create a ObjectSearcher(oSearcher) object to hold the ObjectQuery.
  4. Call the Get method to retrieve the results.

Procedure 4, Remote computers

Ever want to find the status of 100 computers in a datacenter? Better yet, ever want to find out when your coworkers are playing solitaire and then automatically e-mail their boss? WMI was designed from the beginning to be easy to remote, but you must have rights on that other machine to do so.

There is a MMC snapin (WMI control) for setting the properties (such as security) on WMI. For now, try a computer that you are an administrator on.

VB.NET

C#

We see our friends from the SQL example, but there is also a new object called a ManagementScope ( oScope). The ManagementScope sets to scope of our search, which means not only the computer, but also the namespace. Before this example, we just took the defaults. The default computer is obviously our computer, but the namespace is not as obvious. All classes in WMI are in namespaces. A lot of the classes we care about are in the default Namespace (\\root\cimv2 on Windows 2000/XP/2003). In the later section (How do find the class I want?), we will use tools to look at namespaces.

Procedure 5, Methods

Most WMI examples I have found over the years have been worried about getting information. That's fine, but it's only part of what WMI can do for you. WMI provides classes that also have methods (actually WMI has events also).

To use a method, we need to know

  • What object to call the method on.
  • The method name.
  • What are the input parameters.
  • The output parameters.

In the following example, we want to stop the Alerter service.

The object is Win32_Service for Alerter. We could get this object a couple different ways. I choose the way that has the least code by grabbing the object as Win32_Service.Name='Alerter'. The problem is that you need to use the key value (Name for a Win32_Service). If you want to be a little more generic, like terminating every WIN32_Process for Solitaire, you may want to use the SQL method instead.

The rest of the information is a simple. The method is called StopService and there is no input or output parameters (or I don't care about them).

Now we are ready to InvokeMethod!

VB.NET

C#

Procedure 6, Methods Again

The last example was just to get us started. Now let's deal with the parameters.

I want to start solitaire with WMI. A few service packs back, we used to be able to make applications run and appear on your friends' computers this way. Now, if you start a process remotely, it will run non-interactively—no more writing code that starts solitaire on your coworker's computer when the boss walk by.

The problem is now I have an input parameter (CommandLine) and an output parameter (ProcesseId). First we declare an object of type ManagementBaseObject and call the GetMethodParameters (methodname) method. This is like calling a stored procedure and asking what parameters it has, rather that coding them ourselves. Always remember that WMI is very dynamic and methods and their parameters may vary from different versions of Windows, or in some cases, computer to computer.

The output parameters are similar. We use the ManagementBaseObject again to grab the output from the method (InvokeMethod) and then read the parameter we care about (ProcesseID)

VB.NET

C#

Procedure 7, Changing Properties

No, you cannot make your computer run faster by changing the speed property of the processor. Some properties, however, can be changed. The problem is that when we get data from an object and then change it, it is only changed in our programs memory (local property cache). We have to save the change back by using the put method. The put method will save all the property changes on that object.

VB.NET

C#

How do find the class I want?

Okay, by now you are wondering how I know the classes, properties, and methods of the things I need. Simple, I use System.Psychic along with the System.KnowIt.All namespaces.

It really isn't as easy as you might think to find what you are looking for. Microsoft provides two tools—one simple and one detailed. The simple one is called Scriptomatic and it is available from the Script Center on technet.microsoft.com (http://www.microsoft.com/technet/scriptcenter/default.mspx). The other one is called the WMI Administrative Tools and usually find it by going to http://www.microsoft.com/downloads and searching on WMI.

Using Scriptomatic

Scriptomatic is a tool for Windows scripters. It extracts as C:\WindowsScripts\Scriptomatic\scriptomatic.hta. Run the Application and you will see a list of classes in a drop down menu. Just select the class and run the script. Scriptomatic only shows WIN32 classes. There are also the industry (WBEM) standard classes that start CIM. Most CIM classes have an improved WIN32 version, but not all. The second problem with Scriptomatic is that it doesn't show other namespaces. Don't get me wrong; Scriptomatic is a fantastic tool for getting your feet wet in WMI, but you will want to go on to using the WMI administrative tools.

Using WMI Administrative Tools

In WMI administrative tools, several programs exist. We are only going to use CIM Studio, so once you get it installed, run CIM studio.

The first thing it asks for is the namespace. Remember that root\CIMV2 is the default. We can change this later so just click OK.

Just be you, click OK

WOW, doesn't that look complicated! We are going to use only a few of the commands

Finding a Class

I want a class with info about shares. I click the search (red circle number 1 in my picture). Type in share and click GO! This will show all the classes with the word share in it. Highlight Win32_share and click OK.

We should be back to the other screen but over to right we see the properties for that class. Pretty cool! Click the methods tab and see the methods. Better yet, click the help (red circle 4). There is only one help topic for a class. The properties are at the beginning and the methods are at the end. This is how I know the parameters for a method.

Occasionally you will see properties with a pen in the icon. This means that they are writable (this example taken from WIN32_Logical disk).

Let's see what shares we have. If you have been playing, go back to the WIN32_Share Class. Click the instances button (red circle number 2). Now the screen shows all the instances of the Win32_Share class. Double click one of them (I'll pick C$) and we will be back on the properties list but this time the value column is filled in.

Ok, for our final trick, we will try a SQL query. It doesn't matter what class we are in , click the WQL queries button (red circle number 3). Just type the Query in the bottom, give it a name, save it, and click execute. You can try all you queries with out writing any code. If you are curious, my other queries are:

SELECT * FROM win32_NTLogEvent WHERE Logfile='Application' AND SourceName Like 'Norton%'

SELECT * FROM Win32_PingStatus WHERE address='10.0.0.1'

SELECT * FROM win32_Process WHERE name='sol.exe'

The Like operator and the Win32_PingStatus class are not in Windows 2000.

What about the other namespaces?

The available namespaces very greatly from computer to computer. To see the other namespaces, click the Browse for Namespace button just to the left of the Search button we used above. If Starting Namespace, enter root and click Connect. You may now see the other namspaces on your machine. Try each one and see what you find.

Final Notes

I hope this article opens your eyes to the incredibly powerful, yet slightly cryptic little world of WMI.

The entire code can be downloaded for free if you have an account on My SQLSoft. (Accounts can be created free.)

If you have questions, comments, and most of all, if anyone finds any errors, please e-mail me: Mike.Bailey@sqlsoft.com .