Share

I was presented with an interesting problem while at work today….. I needed to get the motherboard manufacturer and model of every Windows-based PC on our network, and I figured the best way to do this is with a WMI query.  I could quickly and easily put together some kind of script that could remotely execute a WMI query on every computer.  What is WMI?  Microsoft Windows Management Instrumentation.  It is the Microsoft implimentation of Web-Based Enterprise Management (WBEM) which uses the Common Information Model (CIM).  WMI connections are made using the Distributed Component Object Model (DCOM).

What does it do?  It allows for remote management of processes, services, registry hives, filesystems, event logs, scheduled tasks, files and folders, etc. and allows you to gather information about computer hardware, software, network, dates and times,  etc., etc.  You can even remotely execute processes.

How do I get it?  That part is easy.  If you’re using Microsoft Windows and you haven’t been living in the stone-age, then you probably already have it.  It was introduced in Microsoft Windows 2000 starting with Service Pack 2.  It can also be added to earlier versions of Windows by installing the .NET Framework SDK and Redistributable package.  So chances are…. you already have it.

How do I use it?  Well, there is a wealth of information on this subject.  For the purposes of this discussion, we’ll focus on queries.  The query syntax is a subset of SQL called WQL.  If you are familiar with SQL, you’ll find this to be trivial.  You can simply pass “SELECT… FROM” statements to the ExecQuery() method to return the requested information.  But first, you need to instantiate a connection to the local or remote machine.  This is typically done via the COM API for WMI.  So any COM-capable language such as VB6, PowerShell, C++, .NET, PowerShell, WinBatch, AutoItV3, and so on (including ASP) can make easy use of this interface.  You can use managed code to impliment WMI providers in .NET Framework 3.5.

For my purposes, I chose to write an AutoIt script.  Using the ObjGet() function I create a connection to remote computer like so:

$objWMI = ObjGet("winmgmts:\\localhost\root\CIMV2")

Note: replace “localhost” with the name or IP of the remote computer you want to query.  Using “localhost” or “127.0.0.1″ will execute on the local machine.

We can now query all attributes of the Win32_ComputerSystem object class:

$objItems = $objWMI.ExecQuery("SELECT * FROM Win32_ComputerSystem", "WQL", 0x10 + 0x20)

Notice the 2 flags at the end…. 0×10 = ReturnImmediately, 0×20 = ForwardOnly.  You could assign these to variables for better readability.

$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20

And then add them together using the “+” operator to combine flag values.  Now from here we can get the object attributes:

If IsObj($objItems) Then
   For $objItem In $objItems
      ConsoleWrite("Manufacturer: " & $objItem.Manufacturer)
      ConsoleWrite("Model: " & $objItem.Model)
      ConsoleWrite("Name: " & $objItem.Caption)
      ConsoleWrite("Description: " & $objItem.Description)
   Next
EndIf

You get the point.  It’s that easy.  If you’d like a more detailed example, I’ve made the project I used at work available for download.  Just click on the item under AutoItV3 called “WMI_ComputerSystemQuery”.  The example project includes the main script and a compiled console application along with dependencies and documentation.

For more information on WMI and how to use it, check out this MSDN article: http://msdn.microsoft.com/en-us/library/aa394582(VS.85).aspx