CPU Auslastung bei DualCore CPU's einzeln Auslesen?



  • Hi!

    Ich möchte gerne die CPU Auslastung auslesen!

    Ich hab dazu diesen Code gefunden:

    // using undocumented functions and structures
    
    #define SystemBasicInformation		0
    #define	SystemPerformanceInformation	2
    #define SystemTimeInformation		3
    
    #define Li2Double(x)	((double)((x).HighPart) * 4.294967296E9 + (double)((x).LowPart))
    
    typedef struct
    {
    	DWORD	dwUnknown1;
    	ULONG	uKeMaximumIncrement;
    	ULONG	uPageSize;
    	ULONG	uMmNumberOfPhysicalPages;
    	ULONG	uMmLowestPhysicalPage;
    	ULONG	UMmHighestPhysicalPage;
    	ULONG	uAllocationGranularity;
    	PVOID	pLowestUserAddress;
    	PVOID	pMmHighestUserAddress;
    	ULONG	uKeActiveProcessors;
    	BYTE	bKeNumberProcessors;
    	BYTE	bUnknown2;
    	WORD	bUnknown3;
    } SYSTEM_BASIC_INFORMATION;
    
    typedef struct
    {
    	LARGE_INTEGER	liIdleTime;
    	DWORD		dwSpare[76];
    } SYSTEM_PERFORMANCE_INFORMATION;
    
    typedef struct
    {
    	LARGE_INTEGER	liKeBootTime;
    	LARGE_INTEGER	liKeSystemTime;
    	LARGE_INTEGER	liExpTimeZoneBias;
    	ULONG			uCurrentTimeZoneID;
    	DWORD			dwReserved;
    } SYSTEM_TIME_INFORMATION;
    
    // NtQuerySystemInformation
    // The function copies the system information of the specified type into a buffer
    // NTSYSAPI 
    // NTSTATUS
    // NTAPI
    // NtQuerySystemInformation(
    //		IN UINT SystemInformationClass,		// information type
    //		OUT PVOID SystemInformation,		// pointer to buffer
    //		IN ULONG SystemInformationLength,	// buffer size in bytes
    //		OUT PULONG ReturnLength OPTIONAL	// pointer to a 32 bit variable that
    //											// receives the number of bytes written
    //											// to the buffer
    // );
    
    typedef LONG (WINAPI *PROCNTQSI) (UINT, PVOID, ULONG, PULONG);
    
    // this functions return the CPU usage of one second using
    // undocumented Windows NT API's
    // this code will not run on Win 9x
    double GetCPUUsages()
    {
    	SYSTEM_BASIC_INFORMATION		SysBaseInfo;
    	SYSTEM_TIME_INFORMATION			SysTimeInfo;
    	SYSTEM_PERFORMANCE_INFORMATION	SysPerfInfo;
    	LONG							status;
    	LARGE_INTEGER					liOldIdleTime = {0, 0};
    	LARGE_INTEGER					liOldSystemTime = {0, 0};
    	double							dbIdleTime;
    	double							dbSystemTime;
    	PROCNTQSI						NtQuerySystemInformation;
    
    	NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(GetModuleHandle(_T("ntdll")), 
    		"NtQuerySystemInformation");
    
    	if (NtQuerySystemInformation)
    	{
    		status = NtQuerySystemInformation(SystemBasicInformation, &SysBaseInfo, 
    			sizeof(SysBaseInfo), NULL);
    
    		if (status == NO_ERROR)
    		{
    			// get system time
    			status = NtQuerySystemInformation(SystemTimeInformation, &SysTimeInfo, 
    				sizeof(SysTimeInfo), NULL);
    
    			if (status == NO_ERROR)
    			{
    				// get system idle time
    				status = NtQuerySystemInformation(SystemPerformanceInformation,
    					&SysPerfInfo, sizeof(SysPerfInfo), NULL);
    
    				if (status == NO_ERROR)
    				{
    					liOldIdleTime = SysPerfInfo.liIdleTime;
    					liOldSystemTime = SysTimeInfo.liKeSystemTime;
    
    					// wait one second
    					::Sleep(1000);
    
    					// get new System time
    					status = NtQuerySystemInformation(SystemTimeInformation, &SysTimeInfo,
    						sizeof(SysTimeInfo), NULL);
    
    					if (status == NO_ERROR)
    					{
    						// get new system idle time
    
    						status = NtQuerySystemInformation(SystemPerformanceInformation,
    							&SysPerfInfo, sizeof(SysPerfInfo), NULL);
    
    						if (status == NO_ERROR)
    						{
    							// current value = new value - old value
    							dbIdleTime = Li2Double(SysPerfInfo.liIdleTime) - Li2Double(liOldIdleTime);
    							dbSystemTime = Li2Double(SysTimeInfo.liKeSystemTime) - Li2Double(liOldSystemTime);
    
    							// currentCpuIdle = IdleTime / SystemTime;
    							dbIdleTime = dbIdleTime / dbSystemTime;
    
    							// currentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors
    							dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SysBaseInfo.bKeNumberProcessors + 0.5;
    						}
    					}
    				}
    			}
    		}
    	}
    
    	return dbIdleTime;
    }
    

    Das Funktioniert soweit ja auch ...

    Jedoch bekomme ich hier nur ein gesamt Ergebnis!

    Ich hätte aber gern die Auslastung Pro CPU Core ...

    Ich Arbeite mit VS2005!

    Vielleicht kann mir ja jemand helfen?

    Bei Code Project hab ich diesen Artikel hier gefunden:

    Getting cpu usage in a Multiprocessor Machine

    Leider bekomme ich wenn ich es mit VC2005 kompilier keine Werte 😞

    Vielleicht hat es ja hier schon mal jmd gemacht 😃

    Gruß & Danke schon mal

    pmneo



  • Tja dann beantworte ich meine Frage eben selbst 😃

    So Funkiontiert es:

    // wmi_test.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
    //
    
    #include "stdafx.h"
    #define _WIN32_DCOM
    #include <iostream>
    using namespace std;
    #include <comdef.h>
    #include <Wbemidl.h>
    
    # pragma comment(lib, "wbemuuid.lib")
    
    int doit()
    {
        HRESULT hres;
    
        // Step 1: --------------------------------------------------
        // Initialize COM. ------------------------------------------
    
        hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
        if (FAILED(hres))
        {
            cout << "Failed to initialize COM library. Error code = 0x" 
                << hex << hres << endl;
            return 1;                  // Program has failed.
        }
    
        // Step 2: --------------------------------------------------
        // Set general COM security levels --------------------------
        // Note: If you are using Windows 2000, you need to specify -
        // the default authentication credentials for a user by using
        // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
        // parameter of CoInitializeSecurity ------------------------
    
        hres =  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
            );
    
        if (FAILED(hres))
        {
            cout << "Failed to initialize security. Error code = 0x" 
                << hex << hres << endl;
            CoUninitialize();
            return 1;                    // Program has failed.
        }
    
        // Step 3: ---------------------------------------------------
        // Obtain the initial locator to WMI -------------------------
    
        IWbemLocator *pLoc = NULL;
    
        hres = CoCreateInstance(
            CLSID_WbemLocator,             
            0, 
            CLSCTX_INPROC_SERVER, 
            IID_IWbemLocator, (LPVOID *) &pLoc);
    
        if (FAILED(hres))
        {
            cout << "Failed to create IWbemLocator object."
                << " Err code = 0x"
                << hex << hres << endl;
            CoUninitialize();
            return 1;                 // Program has failed.
        }
    
        // Step 4: -----------------------------------------------------
        // Connect to WMI through the IWbemLocator::ConnectServer method
    
        IWbemServices *pSvc = NULL;
    
        // Connect to the root\cimv2 namespace with
        // the current user and obtain pointer pSvc
        // to make IWbemServices calls.
        hres = pLoc->ConnectServer(
             _bstr_t(L"ROOT\\CIMV2"), // 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
             );
    
        if (FAILED(hres))
        {
            cout << "Could not connect. Error code = 0x" 
                 << hex << hres << endl;
            pLoc->Release();     
            CoUninitialize();
            return 1;                // Program has failed.
        }
    
        cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
    
        // Step 5: --------------------------------------------------
        // Set security levels on the proxy -------------------------
    
        hres = 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 
        );
    
        if (FAILED(hres))
        {
            cout << "Could not set proxy blanket. Error code = 0x" 
                << hex << hres << endl;
            pSvc->Release();
            pLoc->Release();     
            CoUninitialize();
            return 1;               // Program has failed.
        }
    
        // Step 6: --------------------------------------------------
        // Use the IWbemServices pointer to make requests of WMI ----
    
        // For example, get the name of the operating system
        IEnumWbemClassObject* pEnumerator = NULL;
        IWbemClassObject *pclsObj;
    	int i;
    	while(1)
    	{
    	i=1;
    	hres = pSvc->ExecQuery(
            bstr_t("WQL"), 
    		bstr_t("SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor"),
    
            WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
            NULL,
            &pEnumerator);
    
        if (FAILED(hres))
        {
            cout << "Query for operating system name failed."
                << " Error code = 0x" 
                << hex << hres << endl;
            pSvc->Release();
            pLoc->Release();
            CoUninitialize();
            return 1;               // Program has failed.
        }
    
        // Step 7: -------------------------------------------------
        // Get the data from the query in step 6 -------------------
    
        ULONG uReturn = 0;
    
        while (pEnumerator)
        {
            HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 
                &pclsObj, &uReturn);
    
            if(0 == uReturn)
            {
                break;
            }
    
            VARIANT vtProp;
    
            // Get the value of the Name property
            //hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
    		hr = pclsObj->Get(L"PercentProcessorTime", 0, &vtProp, 0, 0);
            wcout << " CPU Usage of CPU " << i << " : " << vtProp.bstrVal << endl;
            VariantClear(&vtProp);
    		i++;
    	}
    
    	}
    
        // Cleanup
        // ========
    
        pSvc->Release();
        pLoc->Release();
        pEnumerator->Release();
        pclsObj->Release();
        CoUninitialize();
    
        return 0;   // Program successfully completed.
    }
    
    int main(int argc, char **argv)
    {
    	doit();
    
    	Sleep(10000);
    }
    

    Eigentlich genau so wie das von Codeproject, nur das in der Select abfrage nicht von Win32_PerfRawData_PerfOS_Processor sondern von Win32_PerfFormattedData_PerfOS_Processor abgefragt werden muss!

    Gruß pmneo ... BTW das wär doch was für die FAQ?? 😃



  • Aber eher was für die WinAPI-FAQ 😉



  • Kleines Update!!

    Damit der Speicher nicht volläuft sollte der Teil in Step 7 so aussehen:

    // Step 7: -------------------------------------------------
        // Get the data from the query in step 6 -------------------
    
        ULONG uReturn = 0;
    
        while (pEnumerator)
        {
            HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
                &pclsObj, &uReturn);
    
            if(0 == uReturn)
            {
                break;
            }
    
            VARIANT vtProp;
    
            // Get the value of the Name property
            //hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
            hr = pclsObj->Get(L"PercentProcessorTime", 0, &vtProp, 0, 0);
            wcout << " CPU Usage of CPU " << i << " : " << vtProp.bstrVal << endl;
            VariantClear(&vtProp);
    
            //IMPORTANT!!
            pclsObj->Release();
    
            i++;
        }
    
        }
    


  • Jochen Kalmbach schrieb:

    Aber eher was für die WinAPI-FAQ 😉

    Na, dann schieb ich es da mal hin. 🙂
    Falls es dort nicht erwünscht ist, bitte in die MFC FAQ schieben. 😉


Log in to reply