We normally use the WMI to either return information about software and hardware installed, but you probably ever wondered from where this data is obtained?. Well the answer is, this data is obtained from many sources like the WinApi, the Windows Registry, the SMBIOS or custom functions embedded inside of the MOF definition.
WMI Metadata
All the WMI classes have a very rich set of metadata which defines the properties names, data types, descriptions and also each class and property have a special type of attribute called qualifiers which contain addtional metadata information about the WMI element ,within these qualifiers there is one called MappingStrings.
The MSDN documentation about this qualifier states
MappingStrings : Set of values that indicate a path to a location where you can find more information about the origin of a property, class, association, indication, or reference. The mapping string can be a directory path, a URL, a registry key, an include file, reference to a CIM class, or some other format.
This means that by analyzing the content of the MappingStrings qualifier you can determine the source of the data or obtain extra information about this property. Let me explain with a sample. The Win32_DiskDrive WMI class provides information about the physical disks present in the system like Bytes Per Sector, Firmware Revision, Interface Type (SCSI, IDE, USB) and so on. Now if you analize the MappingStrings qualifier of these properties you can determine where is located the information of the disks in the system.
The Code
Check the next function to access the MappingStrings qualifier (if exist) from any WMI class.
{$APPTYPE CONSOLE} uses SysUtils, ActiveX, ComObj, Variants; procedure GetWmiPropsSources(Const NameSpace, ClassName: string); const wbemFlagUseAmendedQualifiers = $00020000; Var Properties : OleVariant; Qualifiers : OleVariant; rgvarProp : OleVariant; rgvarQualif : OleVariant; objSWbemLocator : OleVariant; objSWbemObjectSet : OleVariant; objWMIService : OleVariant; EnumProps : IEnumVariant; EnumQualif : IEnumVariant; pceltFetched : Cardinal; Lindex : Integer; begin //create the WMI Scripting object objSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator'); //connect to the WMi service on the local mahicne objWMIService := objSWbemLocator.ConnectServer('localhost', NameSpace, '', ''); //get the metadata of the WMI class objSWbemObjectSet:= objWMIService.Get(ClassName, wbemFlagUseAmendedQualifiers); //get a pointer to the properties Properties := objSWbemObjectSet.Properties_; //get an enumerator to the properties EnumProps := IUnknown(Properties._NewEnum) as IEnumVariant; //iterate over the properties while EnumProps.Next(1, rgvarProp, pceltFetched) = 0 do begin //get a pointer to the qualifiers of the current property Qualifiers := rgvarProp.Qualifiers_; //get an enumerator to the qualifiers EnumQualif := IUnknown(Qualifiers._NewEnum) as IEnumVariant; //iterate over the qualifiers while EnumQualif.Next(1, rgvarQualif, pceltFetched) = 0 do begin //check the name of the qualifier if SameText('MappingStrings',rgvarQualif.Name) then begin Writeln(rgvarProp.Name); //write the value of the qualifier if not VarIsNull(rgvarQualif.Value) and VarIsArray(rgvarQualif.Value) then for Lindex := VarArrayLowBound(rgvarQualif.Value, 1) to VarArrayHighBound(rgvarQualif.Value, 1) do Writeln(Format(' %s',[String(rgvarQualif.Value[Lindex])])); end; rgvarQualif:=Unassigned; end; rgvarProp:=Unassigned; end; end; begin try CoInitialize(nil); try GetWmiPropsSources('root\cimv2', 'Win32_DiskDrive'); finally CoUninitialize; end; except on E:EOleException do Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode])); on E:Exception do Writeln(E.Classname, ':', E.Message); end; Writeln('Press Enter to exit'); Readln; end.
After of execute the above code you will get a result like this
Availability MIF.DMTF|Operational State|003.5 MIB.IETF|HOST-RESOURCES-MIB.hrDeviceStatus BytesPerSector Win32API|Device Input and Output Structures|DISK_GEOMETRY|BytesPerSector Capabilities MIF.DMTF|Storage Devices|001.9 MIF.DMTF|Storage Devices|001.11 MIF.DMTF|Storage Devices|001.12 MIF.DMTF|Disks|003.7 DeviceID WMI FirmwareRevision Win32API|Device Input and Output Structures|STORAGE_DEVICE_DESCRIPTOR|ProductRevisionOffset Index Win32API|Windows 95/98 Functions|DRIVE_MAP_INFObtInt13Unit InstallDate MIF.DMTF|ComponentID|001.5 InterfaceType Win32API|Device Input and Output Functions|DeviceIoControl Manufacturer Win32Registry|HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi\Scsi Port\Scsi Bus\Target Id\Logical Unit Id\Identifier Win32Registry|Manufacturer MaxMediaSize MIF.DMTF|Sequential Access Devices|001.2 MediaLoaded Win32API|Device Input and Output Structures|DISK_GEOMETRY|MediaType|FixedMedia MediaType Win32API|Device Input and Output Structures|DISK_GEOMETRY|MediaType Model Win32Registry|HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi\Scsi Port\Scsi Bus\Target Id\Logical Unit Id\Identifier Win32Registry|ProductId Partitions Win32API|Device Input and Output Structures|PARTITION_INFORMATION|RecognizedPartition SCSIBus Win32API|Device Input and Output Structures|SCSI_ADDRESS|PathId SCSILogicalUnit Win32API|Device Input and Output Structures|SCSI_ADDRESS|Lun SCSIPort Win32API|Device Input and Output Structures|SCSI_ADDRESS|PortNumber SCSITargetId Win32API|Device Input and Output Structures|SCSI_ADDRESS|TargetId SectorsPerTrack Win32API|Device Input and Output Structures|DISK_GEOMETRY|SectorsPerTrack SerialNumber Win32API|Device Input and Output Structures|STORAGE_DEVICE_DESCRIPTOR|SerialNumberOffset Signature Win32API|Device Input and Output Structures|DRIVE_LAYOUT_INFORMATION|Signature Size Win32API|Device Input and Output Structures|DISK_GEOMETRY StatusInfo MIF.DMTF|Operational State|003.3 TotalCylinders Win32API|Device Input and Output Structures|DISK_GEOMETRY|Cylinders TotalHeads Win32API|Device Input and Output Structures|DISK_GEOMETRY|TracksPerCylinder TotalSectors Win32API|Device Input and Output Structures|DISK_GEOMETRY|SectorsPerTrack TotalTracks Win32API|Device Input and Output Structures|DISK_GEOMETRY|TracksPerCylinder TracksPerCylinder Win32API|Device Input and Output Structures|DISK_GEOMETRY|TracksPerCylinder
As you can see most of the properties of this class have a MappingStrings qualifier which shows the source (Win32API, Win32Registry, MIF.DMTF) of the data.
Finally if you are interested on this topic take a look to the WMI Delphi Code Creator which includes this feature.
Pingback: /*Prog*/ Delphi-Neftalí /*finProg*/ » Una quincena más… (11/04/2012)
April 12, 2012 at 4:17 am
hot stuff, much thX !!!!!!
June 5, 2012 at 11:00 am
I have read that the WMI can be used to read the CPU Thermometer. Could you give a sample of how this could be done?
June 5, 2012 at 7:11 pm
Try using the MSAcpi_ThermalZoneTemperature WMI class which is located in the root\WMI namespace, if you want help to access this class, try using the wmi-delphi-code-creator http://code.google.com/p/wmi-delphi-code-creator/