Introduction
We normally find a lot of ways and a number of resources to use WMI or to get information from “Windows Management Instrumentation” while using Visual Basic 6 and C#, but I could not find a single resource describing the same thing in Visual C++. MSDN resources are also very limited in this context.
Code
Following is the code on how to get the current processor load from a WMI class Win32_Processor
defined in a .mof file. .mof files are managed object files which have a typical way of defining classes and methods.
WMI provides the COM service which is used to connect to the WMI services. The important parts of the code include:
bstrNamespace
: The initialization of this variable is very tricky. The first three forward slashes
represent the Host Computer name from which you want to get information from. A “.” Indicates that information is to be obtained from the same computer on which you are working. You can give any network name here but getting information from the network depends upon your Access Rights, etc. cimv2
is the namespace containing the Win32_Processor
class.
pIWbemLocator
is the argument in which we get the Interface pointer.
- After that, we call the function
ConnectServer
of the pIWbemLocator
to get a pointer to pWbemServices
.
- WMI uses its own Query Language to get information known as WQL (the acronym for WMI Query Language). So, when calling the function
ExecQuery
, we have to specify the language as its first argument. Second argument is the Query itself. Last argument is important because here we get a pointer to an Enumeration
object through which we can enumerate through the objects available. This enumeration is important because consider the case that we want to know the information about running processes and we are using Win32_Process
class for this purpose. Then through this enumeration object, we can go through different processes one by one.
- By calling the
Reset
and Next
methods of pEnumObject
, we are moving through the objects. We get the pointer to an object in pClassObject
.
- The last function through which we get the actual value of a property is
Get
. We pass a BSTR
to this function to get the value in a variant.
The code for getting Processor Load is in a thread which keeps on running and posts message to UI to update the Progress bar. Here is the Thread function.
UINT GetProcessorLoad( LPVOID pParam )
{
CUsingWMIDlg* dlg = (CUsingWMIDlg*)pParam;
CoInitialize(NULL);
HRESULT hRes = CoInitializeSecurity( NULL, -1, NULL,
NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL,
EOAC_NONE, 0);
if(hRes != S_OK) return 0;
CComPtr<iwbemlocator> pIWbemLocator;
CComPtr<iwbemservices> pIWbemServices;
CComPtr<ienumwbemclassobject> pIEnumObject;
CComBSTR bstrNamespace(_T("root\\cimv2"));
hRes = pIWbemLocator.CoCreateInstance(CLSID_WbemAdministrativeLocator);
if(hRes != S_OK) return 0;
hRes = pIWbemLocator->ConnectServer(bstrNamespace, NULL,
NULL, NULL, 0, NULL, NULL, &pIWbemServices);
if(hRes != S_OK) return 0;
while(true)
{
CComBSTR bstrQuery(_T("Select * from Win32_Processor"));
CComBSTR bstrQL(_T("WQL"));
hRes = pIWbemServices->ExecQuery
(bstrQL, bstrQuery, WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pIEnumObject);
ULONG uCount = 1, uReturned;
CComPtr<iwbemclassobject> pIClassObject;
hRes = pIEnumObject->Reset();
hRes = pIEnumObject->Next
(WBEM_INFINITE, uCount, &pIClassObject, &uReturned);
if(hRes != S_OK) return 0;
CComVariant var;
CComBSTR bstrProp(_T("LoadPercentage"));
hRes = pIClassObject->Get(bstrProp, 0, &var, NULL, NULL);
if(hRes != S_OK) return 0;
int * value = new int(var.lVal);
dlg->PostMessage(WM_USER+1, (WPARAM) value);
pIEnumObject.Release();
}
return 1;
}
Conclusion
This was the shortest method I was able to work out to get information from any WMI class. You can simply change the class name in the Query and Property Name while calling Get
method and you will get information from all the classes supported in your OS. I have now tested this code in Windows 7, Windows XP, Win2000, Win2003 and Win2008.
Update
I found out that the code associated with this article was very badly written. After all, I did this when I was a student. Now that I know a tiny bit more, I am updating the code. I have now used Smart Pointers and I have also updated the example App to show the Processor load in a Progress Bar. Furthermore, this is now a Visual Studio 2008 project.
Another fix was to add a lib file in linker settings.