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
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.
CoInitialize(NULL);
IWbemLocator * pIWbemLocator = NULL;
IWbemServices * pWbemServices = NULL;
IEnumWbemClassObject * pEnumObject = NULL;
BSTR bstrNamespace = (L"//./root\\cimv2");
HRESULT hRes = CoCreateInstance (
CLSID_WbemAdministrativeLocator,
NULL ,
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER ,
IID_IUnknown ,
( void ** ) & pIWbemLocator
) ;
if (SUCCEEDED(hRes))
{
hRes = pIWbemLocator->ConnectServer(
bstrNamespace,
NULL,
NULL,
NULL,
0,
NULL,
NULL,
&pWbemServices
);
}
BSTR strQuery = (L"Select * from win32_Processor");
BSTR strQL = (L"WQL");
hRes = pWbemServices->ExecQuery(strQL, strQuery,
WBEM_FLAG_RETURN_IMMEDIATELY,NULL,&pEnumObject);
ULONG uCount = 1, uReturned;
IWbemClassObject * pClassObject = NULL;
hRes = pEnumObject->Reset();
hRes = pEnumObject->Next(WBEM_INFINITE,uCount, &pClassObject, &uReturned);
VARIANT v;
BSTR strClassProp = SysAllocString(L"LoadPercentage");
hRes = pClassObject->Get(strClassProp, 0, &v, 0, 0);
SysFreeString(strClassProp);
_bstr_t bstrPath = &v;
char* strPath=(char*)bstrPath;
if (SUCCEEDED(hRes))
MessageBox(strPath);
else
MessageBox(”Error in getting object”);
VariantClear( &v );
pIWbemLocator->Release();
pWbemServices->Release();
pEnumObject->Release();
pClassObject->Release();
CoUninitialize();
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 tested this code in Windows 2000
Professional. I hope it will work well for Win XP but probably not in
previous versions of windows because they don’t support a lot of WMI
classes.