WMI Scripting with AutoIt
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

February 18th, 2009 at 9:12 am
We did much the same thing – we did find that a number of older machines running XP had null values in one or more fields. What we did not find was a field with a chipset name
like X38, G41, 955X … – the names that Intel uses. We looked through most of WMI – if seems if the chipset name is not in ComputerSystem or its child it must be well hidden. Did you have any better luck with chipset names on your computers?
February 18th, 2009 at 5:45 pm
Well…. that was one of the things I’d hoped to extrapolate from this type of query. I looked into querying the Win32_BIOS class, but judging by the MSDN documentation, it doesn’t look like you can get the chipset from it. I’m thinking this could probably be accomplished by querying the Win32_SystemDevices class…. though I haven’t figured out exactly how yet. For us, getting the “Model” property from the Win32_ComputerSystem class has been sufficient because we use mostly Intel and SuperMicro motherboards. The “Model” property for these boards typically returns a valid model that we can then look up and get the specs on. In the case of Intel, the chipset typically makes up part of the model name, like “D946GZ” for example. In this case “D946GZ” tells me that it’s a desktop-class board and uses the Intel 946-series chipset.
Most of the time this is all the information I need, but I’m quite sure there is a more accurate approach. I just haven’t found it yet.