Summary
WMI is a bulky service with a COM-based API that was meant to help computer technicians write administrative maintenance scripts. It isn't meant for application use and if a user stops the service for security reasons relying on it can leave your program high and dry.
One of the things people often fall back on WMI for is system information, particularly information retrieved from the SMBIOS data block. That's usually just fine, since it seldom makes sense for applications to use such information anyway, so WMI admin scripts usually more than suffice.
But some people still want to do this, as unreliable as the SMBIOS info is. So here is an approach that bypasses WMI to get the same information.
The Code
This is a VB6 collection class SmbiosInformation and a small item class SmbiosItem. It requires no 3rd party libraries and makes use of GetSystemFirmwareTable() in Kernel32.dll to retrieve the raw data. Once retrieved it browses (some would say "parses" but we really aren't) the compound structure for data items.
It is important to note that this API entrypoint did not become available until Windows Server 2003 SP1 and Windows XP Professional 64-bit SP3. So effectively none of this applies to pre-Vista versions of Windows, all of which are officially unsupported now anyway.
Limitations, Opportunity
SmbiosInformation is not exhaustive in its browsing and reporting, returning only a subset of the available information.
You could choose to add more items, delete items you do not care about, or change the way some data items are reported. For example the "ChassisType" item is currently reported as a Byte value from 0-127 as stored in the raw data block, but you could translate those to friendly String values instead.
None of this seems very close to "perfect." Depending on the machine you might get various serial number values or you might get an empty String or a String of all 0 characters. You might get "BaseBoardxxxx" items or you might get none of them if the machine doesn't provide them. There is a theoretical way to detect HyperThreading capability, but it fails on some systems, probably because the BIOS is reporting many values according to how it has them set during boot. On some machines the BIOS version comes back as 0.0, which isn't correct.
Lots of String items come back as "To Be Filled By O.E.M." instead of a useful value, others come back as empty Strings.
Some kinds of data can be complex. CPUs are reported by socket, and a given machine may have more than one socket and CPU chip, so SmbiosInformation reports those as sub-collections of data, one per socket. There can be multiple Memory Array entries in the raw data, so SmbiosInformation just sums them.
Helpful References
I found SMBIOS Demystified helpful but really ended up even more confused. It could have been written far better, but the topic really is confusing so I can't fault the author too much. I'm sure not volunteering to do so!
But he did provide a link to System Management BIOS where you can download PDFs of different versions of the actual specs. This is critical information if you want to expand on what the provided code does.
Demo
I have attached a ZIP archive containing these classes and a simple Project1 program that uses them.
The demo gets the information, and then reports results two ways:
![Name: sshot.png
Views: 21
Size: 23.4 KB]()
Full Dump
Useful?
You be the judge. Results are highly variable from machine to machine that I tested. If it is any comfort, if you can't get it this way you can't get it via WMI either.
Of course WMI covers lots of other things too - such as letting people get remote access to your machine! It is not a safe thing to have running at all, but Windows itself is becoming more and more dependent on it. Even some of the administrative Control Panel applets need the WMI Service running to work now.
WMI is a bulky service with a COM-based API that was meant to help computer technicians write administrative maintenance scripts. It isn't meant for application use and if a user stops the service for security reasons relying on it can leave your program high and dry.
One of the things people often fall back on WMI for is system information, particularly information retrieved from the SMBIOS data block. That's usually just fine, since it seldom makes sense for applications to use such information anyway, so WMI admin scripts usually more than suffice.
But some people still want to do this, as unreliable as the SMBIOS info is. So here is an approach that bypasses WMI to get the same information.
The Code
This is a VB6 collection class SmbiosInformation and a small item class SmbiosItem. It requires no 3rd party libraries and makes use of GetSystemFirmwareTable() in Kernel32.dll to retrieve the raw data. Once retrieved it browses (some would say "parses" but we really aren't) the compound structure for data items.
It is important to note that this API entrypoint did not become available until Windows Server 2003 SP1 and Windows XP Professional 64-bit SP3. So effectively none of this applies to pre-Vista versions of Windows, all of which are officially unsupported now anyway.
Limitations, Opportunity
SmbiosInformation is not exhaustive in its browsing and reporting, returning only a subset of the available information.
You could choose to add more items, delete items you do not care about, or change the way some data items are reported. For example the "ChassisType" item is currently reported as a Byte value from 0-127 as stored in the raw data block, but you could translate those to friendly String values instead.
None of this seems very close to "perfect." Depending on the machine you might get various serial number values or you might get an empty String or a String of all 0 characters. You might get "BaseBoardxxxx" items or you might get none of them if the machine doesn't provide them. There is a theoretical way to detect HyperThreading capability, but it fails on some systems, probably because the BIOS is reporting many values according to how it has them set during boot. On some machines the BIOS version comes back as 0.0, which isn't correct.
Lots of String items come back as "To Be Filled By O.E.M." instead of a useful value, others come back as empty Strings.
Some kinds of data can be complex. CPUs are reported by socket, and a given machine may have more than one socket and CPU chip, so SmbiosInformation reports those as sub-collections of data, one per socket. There can be multiple Memory Array entries in the raw data, so SmbiosInformation just sums them.
Helpful References
I found SMBIOS Demystified helpful but really ended up even more confused. It could have been written far better, but the topic really is confusing so I can't fault the author too much. I'm sure not volunteering to do so!
But he did provide a link to System Management BIOS where you can download PDFs of different versions of the actual specs. This is critical information if you want to expand on what the provided code does.
Demo
I have attached a ZIP archive containing these classes and a simple Project1 program that uses them.
The demo gets the information, and then reports results two ways:
- An initial MsgBox presenting a few values retrieved by key (Name).
- A full dump in a sortable ListView, retrieved by enumeration.
Full Dump
Useful?
You be the judge. Results are highly variable from machine to machine that I tested. If it is any comfort, if you can't get it this way you can't get it via WMI either.
Of course WMI covers lots of other things too - such as letting people get remote access to your machine! It is not a safe thing to have running at all, but Windows itself is becoming more and more dependent on it. Even some of the administrative Control Panel applets need the WMI Service running to work now.