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 !
LVL 25
InteractiveMindAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
Check out http://www.codeproject.com/system/cpuusage.asp ("How to get CPU usage by performance counters (without PDH)") which IMO is the simplest way to do that and should work with Dev-C++. An advanced way would be PDH: http://www.codeproject.com/system/cpdh.asp ("CPdh v1.03 - NT Performance Info")
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
InteractiveMindAuthor Commented:
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
0
jkrCommented:
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++
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

InteractiveMindAuthor Commented:
Perhaps I need to add a library or something ?  :-\
0
jkrCommented:
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'
0
InteractiveMindAuthor Commented:
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
0
jkrCommented:
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;
}
0
InteractiveMindAuthor Commented:
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? :-\
0
jkrCommented:
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
};
0
InteractiveMindAuthor Commented:
Hmm; making that change is now resulting in 23 errors  :-\
0
jkrCommented:
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
0
InteractiveMindAuthor Commented:
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
0
AxterCommented:
I use boost::progress_timer.
Check out following link:
http://athene.berlios.de/classboost_1_1progress__timer.html
0
jkrCommented:
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.
0
InteractiveMindAuthor Commented:
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();

?
0
InteractiveMindAuthor Commented:
Oh, that's the warning thing....

nvm :)

Is there a way to disable warnings in Dev-C++ ? :)
0
InteractiveMindAuthor Commented:
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..)
0
jkrCommented:
Can you check the registry whether the flags have been set correctly?
0
InteractiveMindAuthor Commented:
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) ...
0
jkrCommented:
Ah, that's the problem - change


     DWORD dw = bEnable ? 1 : 0;

to


     DWORD dw = bEnable ? 0 : 1;
0
InteractiveMindAuthor Commented:
..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 !!
0
jkrCommented:
You're most welcome ;o)
0
InteractiveMindAuthor Commented:
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. :)

http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_21790438.html

Cheers.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.