Link to home
Create AccountLog in
Avatar of InteractiveMind
InteractiveMindFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Function to get CPU usage of specified process

Hello,

I really need a function that will take a string (or equivalent) of the name of a process, and return it's CPU usage at that moment in time.

I've tried coding something myself based on the huge number of stuff in the PAQ's, but am not getting anywhere...

My IDE is Dev-C++.

[BTW, I can guarantee that only 1 process with the specified name will be running at any given time].


Thanks very much !
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
Avatar of InteractiveMind

ASKER

Hey jkr.

I've shoved the source files provided in that link into a new project in Dev-C++, and have tried to compile - but am getting a load of errors...

Just a few of which area:

atlbase.h: No such file or directory.
comdef.h: No such file or directory.
.
.
and a few syntax errors..


Any ideas ?

Thanks
Hm, 'atlbase.h' is used only in CpuUsage.cpp - and only for 'CRegKey' in

BOOL CCpuUsage::EnablePerformaceCounters(BOOL bEnable)
{
      if (GetPlatform() != WIN2K_XP)
            return TRUE;

      CRegKey regKey;
      if (regKey.Open(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\PerfOS\\Performance") != ERROR_SUCCESS)
            return FALSE;

      regKey.SetValue(!bEnable, "Disable Performance Counters");
      regKey.Close();

      if (regKey.Open(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\PerfProc\\Performance") != ERROR_SUCCESS)
            return FALSE;

      regKey.SetValue(!bEnable, "Disable Performance Counters");
      regKey.Close();

      return TRUE;
}

If you change that to regular Win32 Registry APIs, you can just delete the lines

#include "stdafx.h"
#include <atlbase.h>      // for CRegKey use

'comdef.h' however should be availyble with Dev-C++
Perhaps I need to add a library or something ?  :-\
No, 'comdef.h' is for the basic COM support classes. But you can eliminate this issue by changing

            // Look for instance pInstanceName
            _bstr_t bstrInstance;
            _bstr_t bstrInputInstance = pInstanceName;
            for( int k=0; k < pPerfObj->NumInstances; k++ )
            {
                bstrInstance = (wchar_t *)((PBYTE)pPerfInst + pPerfInst->NameOffset);
                if (!stricmp((LPCTSTR)bstrInstance, (LPCTSTR)bstrInputInstance))
                {
                    pCounterBlock = (PPERF_COUNTER_BLOCK) ((LPBYTE) pPerfInst + pPerfInst->ByteLength);
                    break;
                }
               
                // Get the next instance.

                pPerfInst = NextInstance( pPerfInst );
            }

to

            // Look for instance pInstanceName
            wchar_t* bstrInstance;
            wchar_t* bstrInputInstance = new wchar_t[strlen(pInstanceName) + 1];
                  mbstowcs(bstrInputInstance,pInstanceName,strlen(pInstanceName) + 1);
            for( int k=0; k < pPerfObj->NumInstances; k++ )
            {
                bstrInstance = (wchar_t *)((PBYTE)pPerfInst + pPerfInst->NameOffset);
                if (!_wcsicmp(bstrInstance, bstrInputInstance))
                {
                    pCounterBlock = (PPERF_COUNTER_BLOCK) ((LPBYTE) pPerfInst + pPerfInst->ByteLength);
                    break;
                }
               
                // Get the next instance.

                pPerfInst = NextInstance( pPerfInst );
            }
            delete [] bstrInputInstance;

in 'PerfCounters.h' and substitute 'comdef.h' by 'string.h'
Ah k; that seems to have gotten rid of the comdef.h error message..

As for "change that to regular Win32 Registry APIs" ... how would I do this?

Ta
Just like

BOOL CCpuUsage::EnablePerformaceCounters(BOOL bEnable)
{
     if (GetPlatform() != WIN2K_XP)
          return TRUE;

     DWORD dw = bEnable ? 1 : 0;
     HKEY regKey;
     if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\PerfOS\\Performance",0, KEY_SET_VALUE, &regKey))
          return FALSE;

     RegSetValueEx(rekKey, "Disable Performance Counters", 0, REG_DWORD, (LPVOID) &dw, sizeof(DWORD));
     RegCloseKey(regKey);

     if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\PerfProc\\Performance",0, KEY_SET_VALUE, &regKey))
          return FALSE;

     RegSetValueEx(rekKey, "Disable Performance Counters", 0, REG_DWORD, (LPVOID) &dw, sizeof(DWORD));
     RegCloseKey(regKey);

     return TRUE;
}
Yup, that's sorted that bit.... now just another 19 error messages :(

They mostly seem to be syntax errors.. :\


Here's my Compile Log:


Compiler: Default compiler
Building Makefile: "C:\Documents and Settings\rob\Desktop\Makefile.win"
Executing  make...
make.exe -f "C:\Documents and Settings\rob\Desktop\Makefile.win" all
g++.exe -c CpuUsage_src/CpuUsage.cpp -o CpuUsage_src/CpuUsage.o -I"C:/Program Files/Dev-Cpp/include/c++/3.3.1"  -I"C:/Program Files/Dev-Cpp/include/c++/3.3.1/mingw32"  -I"C:/Program Files/Dev-Cpp/include/c++/3.3.1/backward"  -I"C:/Program Files/Dev-Cpp/lib/gcc-lib/mingw32/3.3.1/include"  -I"C:/Program Files/Dev-Cpp/include"  -I"C:/Program Files/Java/jdk1.5.0_01/include"  -I"C:/Program Files/Java/jdk1.5.0_01/include/win32"  

CpuUsage_src/CpuUsage.cpp:47: error: syntax error before numeric constant
CpuUsage_src/CpuUsage.cpp:48: error: ISO C++ forbids declaration of `PLATFORM'
   with no type
CpuUsage_src/CpuUsage.cpp:50: error: syntax error before `)' token
CpuUsage_src/CpuUsage.cpp:53: error: syntax error before `.' token

CpuUsage_src/CpuUsage.cpp: In member function `BOOL
   CCpuUsage::EnablePerformaceCounters(int)':
CpuUsage_src/CpuUsage.cpp:82: error: `GetPlatform' undeclared (first use this
   function)
CpuUsage_src/CpuUsage.cpp:82: error: (Each undeclared identifier is reported
   only once for each function it appears in.)
CpuUsage_src/CpuUsage.cpp:82: error: `WIN2K_XP' undeclared (first use this
   function)

CpuUsage_src/CpuUsage.cpp:90: error: invalid conversion from `void*' to `const
   BYTE*'

CpuUsage_src/CpuUsage.cpp:96: error: invalid conversion from `void*' to `const
   BYTE*'

CpuUsage_src/CpuUsage.cpp: In member function `int CCpuUsage::GetCpuUsage()':
CpuUsage_src/CpuUsage.cpp:111: error: ISO C++ forbids declaration of `PLATFORM'
   with no type
CpuUsage_src/CpuUsage.cpp:111: error: syntax error before `=' token

CpuUsage_src/CpuUsage.cpp:131: error: `Platform' undeclared (first use this
   function)

CpuUsage_src/CpuUsage.cpp: In member function `int CCpuUsage::GetCpuUsage(const
   TCHAR*)':

CpuUsage_src/CpuUsage.cpp:179: error: ISO C++ forbids declaration of `PLATFORM'
   with no type
CpuUsage_src/CpuUsage.cpp:179: error: syntax error before `=' token

CpuUsage_src/CpuUsage.cpp: In member function `int CCpuUsage::GetCpuUsage(long
   unsigned int)':
CpuUsage_src/CpuUsage.cpp:226: error: ISO C++ forbids declaration of `PLATFORM'
   with no type
CpuUsage_src/CpuUsage.cpp:226: error: syntax error before `=' token

CpuUsage_src/PerfCounters.h: In member function `void
   CPerfCounters<T>::CBuffer::Reset() [with T = LONGLONG]':
CpuUsage_src/PerfCounters.h:140:   instantiated from `void CPerfCounters<T>::QueryPerformanceData(PERF_DATA_BLOCK**, long unsigned int, long unsigned int) [with T = LONGLONG]'
CpuUsage_src/PerfCounters.h:22:   instantiated from `T CPerfCounters<T>::GetCounterValue(PERF_DATA_BLOCK**, long unsigned int, long unsigned int, const TCHAR*) [with T = LONGLONG]'
CpuUsage_src/CpuUsage.cpp:151:   instantiated from here
CpuUsage_src/PerfCounters.h:95: warning: passing NULL used for non-pointer
   argument passing 2 of `void* memset(void*, int, unsigned int)'
CpuUsage_src/PerfCounters.h:95: warning: argument to non-pointer type `int'
   from NULL

make.exe: *** [CpuUsage_src/CpuUsage.o] Error 1

Execution terminated



Is there really no easier way of doing this? :-\
Nope. But, the error mainly boils down to

typedef enum
{
      WINNT,      WIN2K_XP, WIN9X, UNKNOWN
}PLATFORM;

which is actually valid. You could try

enum PLATFORM
{
      WINNT,      WIN2K_XP, WIN9X, UNKNOWN
};
Hmm; making that change is now resulting in 23 errors  :-\
What about

enum _PLATFORM
{
     WINNT,     WIN2K_XP, WIN9X, UNKNOWN
} PLATFORM;

?

If this also goes wrong, make that

typedef int PLATFORM;
#define WINNT 1
#define WIN2K_XP 2
#define WIN9X 3
#define UNKNOWN -1
Okay, the last suggestion sorts most of that....

Just 5 errors left  :)


Compiler: Default compiler
Building Makefile: "C:\Documents and Settings\rob\Desktop\Makefile.win"
Executing  make...
make.exe -f "C:\Documents and Settings\rob\Desktop\Makefile.win" all
g++.exe -c CpuUsage_src/CpuUsage.cpp -o CpuUsage_src/CpuUsage.o -I"C:/Program Files/Dev-Cpp/include/c++/3.3.1"  -I"C:/Program Files/Dev-Cpp/include/c++/3.3.1/mingw32"  -I"C:/Program Files/Dev-Cpp/include/c++/3.3.1/backward"  -I"C:/Program Files/Dev-Cpp/lib/gcc-lib/mingw32/3.3.1/include"  -I"C:/Program Files/Dev-Cpp/include"  -I"C:/Program Files/Java/jdk1.5.0_01/include"  -I"C:/Program Files/Java/jdk1.5.0_01/include/win32"  

CpuUsage_src/CpuUsage.cpp: In member function `BOOL
   CCpuUsage::EnablePerformaceCounters(int)':
CpuUsage_src/CpuUsage.cpp:90: error: invalid conversion from `void*' to `const
   BYTE*'
CpuUsage_src/CpuUsage.cpp:96: error: invalid conversion from `void*' to `const
   BYTE*'

CpuUsage_src/PerfCounters.h: In member function `void
   CPerfCounters<T>::CBuffer::Reset() [with T = LONGLONG]':
CpuUsage_src/PerfCounters.h:140:   instantiated from `void CPerfCounters<T>::QueryPerformanceData(PERF_DATA_BLOCK**, long unsigned int, long unsigned int) [with T = LONGLONG]'
CpuUsage_src/PerfCounters.h:22:   instantiated from `T CPerfCounters<T>::GetCounterValue(PERF_DATA_BLOCK**, long unsigned int, long unsigned int, const TCHAR*) [with T = LONGLONG]'
CpuUsage_src/CpuUsage.cpp:151:   instantiated from here
CpuUsage_src/PerfCounters.h:95: warning: passing NULL used for non-pointer
   argument passing 2 of `void* memset(void*, int, unsigned int)'
CpuUsage_src/PerfCounters.h:95: warning: argument to non-pointer type `int'
   from NULL

make.exe: *** [CpuUsage_src/CpuUsage.o] Error 1

Execution terminated


:D
I use boost::progress_timer.
Check out following link:
http://athene.berlios.de/classboost_1_1progress__timer.html
Ah, getting closer - that should be

BOOL CCpuUsage::EnablePerformaceCounters(BOOL bEnable)
{
     if (GetPlatform() != WIN2K_XP)
          return TRUE;

     DWORD dw = bEnable ? 1 : 0;
     HKEY regKey;
     if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\PerfOS\\Performance",0, KEY_SET_VALUE, &regKey))
          return FALSE;

     RegSetValueEx(rekKey, "Disable Performance Counters", 0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
     RegCloseKey(regKey);

     if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\PerfProc\\Performance",0, KEY_SET_VALUE, &regKey))
          return FALSE;

     RegSetValueEx(rekKey, "Disable Performance Counters", 0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
     RegCloseKey(regKey);

     return TRUE;
}

The rest are only warnings.
Okay, one last thing:

CpuUsage_src/PerfCounters.h: In member function `void
   CPerfCounters<T>::CBuffer::Reset() [with T = LONGLONG]':
CpuUsage_src/PerfCounters.h:140:   instantiated from `void CPerfCounters<T>::QueryPerformanceData(PERF_DATA_BLOCK**, long unsigned int, long unsigned int) [with T = LONGLONG]'
CpuUsage_src/PerfCounters.h:22:   instantiated from `T CPerfCounters<T>::GetCounterValue(PERF_DATA_BLOCK**, long unsigned int, long unsigned int, const TCHAR*) [with T = LONGLONG]'
CpuUsage_src/CpuUsage.cpp:151:   instantiated from here

Apparently it doesn't like this line in PerfCounters.h:

Buffer.Reset();

?
Oh, that's the warning thing....

nvm :)

Is there a way to disable warnings in Dev-C++ ? :)
Okay, that's all compiling fine now, and has produced an exe :)

However ...

When I run the program, the "SystemWide Cpu Usage" is stuck at 100%, and the other two measurements are both at 0%...

(But, if I run the pre-compiled demo from that site, it's giving correct output..)
Can you check the registry whether the flags have been set correctly?
If you mean:

HKLM\SYSTEM\CurrentControlSet\Services\PerfOS\Performance\Disable Performance Counters
and
HKLM\SYSTEM\CurrentControlSet\Services\PerfProc\Performance\Disable Performance Counters

Then yes, they exist (both with value 0x00000001) ...
Ah, that's the problem - change


     DWORD dw = bEnable ? 1 : 0;

to


     DWORD dw = bEnable ? 0 : 1;
..And it works !!!

Magic.

Thanks very much for going through this with me, jkr.. I tried to get this thing working many months ago - with no luck.
So, I'm really happy now :D

Thanks !!
You're most welcome ;o)
By the way; it would seem that the GetCpuUsage() returns 0 the first time it's called [everytime].. This is quite obvious when looking at the code... but is there a way to retrieve the CPU usage with only a single call to that function? (Because I need to shove it into a DLL, and calling that function twice within the DLL doesn't seem to be working...)

I think that I've had more than my share of help in this thread [for just 500 points] -- so have posted a new thread regarding this problem. :)

https://www.experts-exchange.com/questions/21790438/Follow-up-Function-to-get-CPU-usage-of-specified-process.html

Cheers.