出處:http://www.codeproject.com/Articles/10538/Getting-CPU-Usage-in-a-Multiprocessor-Machine
Introduction
Ever since I saw ‘Performance’ application on Windows 2000, I wondered if there is a way / Windows API to programmatically determine CPU usage for each of the individual CPUs in a multi-processor machine. Though there are many articles for getting the CPU usage, none helped when it came to multi-processor machines.
After some digging in MSDN, I could find WMI (Windows Management and Instrumentation) has a few performance counter classes. I chose to use the Win32_PerfRawData_PerfOS_Processor class in this case as it is supported on Windows 2000 onwards.
How to use it?
Follow these seven steps:
Step 1: Initialize COM:
CoInitializeEx(0, COINIT_MULTITHREADED);
Step 2: Set COM security levels:
CoInitializeSecurity( NULL, -1, // COM authentication NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved );
Step 3: Obtain the initial locator to WMI:
IWbemLocator *pLoc = NULL; hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc);
Step 4: Connect to WMI through the IWbemLocator::ConnectServer method:
IWbemServices *pSvc = NULL; // Connect to the rootcimv2 namespace with // the current user and obtain pointer pSvc // to make IWbemServices calls. hres = pLoc->ConnectServer( _bstr_t(L"ROOTCIMV2"), // Object path of WMI namespace NULL, // User name. NULL = current user NULL, // User password. NULL = current 0, // Locale. NULL indicates current NULL, // Security flags. 0, // Authority (e.g. Kerberos) 0, // Context object &pSvc // pointer to IWbemServices proxy );
Step 5: Set security levels on the proxy:
CoSetProxyBlanket( pSvc, // Indicates the proxy to set RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx NULL, // client identity EOAC_NONE // proxy capabilities );
Step 6: Use the IWbemServices pointer to make requests of WMI:
IEnumWbemClassObject* pEnumerator = NULL; HRESULT hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * FROM Win32_PerfRawData_PerfOS_Processor"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
Step 7: Get data from the query in step 6.
IWbemClassObject *pclsObj; while (1) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if(0 == uReturn) { break; } VARIANT vtProp; VariantInit(&vtProp); hr = pclsObj->Get(L"PercentProcessorTime", 0, &vtProp, 0, 0); // Use it hr = pclsObj->Get(L"TimeStamp_Sys100NS", 0, &vtProp, 0, 0); // Use it }
Note
I have tried to keep the source code in the attached project simple. So I have taken the number of processors as the input though you may like to programmatically get the number of processors using GetSystemInfo Win32 API.
I have tested it on Microsoft Windows 2000 Professional OS running on a dual processor machine. It should work on Windows XP/ Windows 2003 Server as well.
License
About the Author
India