-
March 23rd, 2025, 06:13 AM
#1
Process info display
Hello,
I need to display the information of a process in c++. (ie number of threads in c++ , belonging to a process etc) in windows
I am not system level programmer , coming from linux user level prog.
I tried to go through the windows documentation and came up with the following experiment program, before trying to fit in into the actual code.
I tried to create a calculator process in the main(), and then pass that process Id to a function (I copied from the microsoft website). In this program, it tries to loop through all the process. It then compares the process Id with the passed process Id.
It uses the if( !Process32First( hProcessSnap, &pe32 ) ), to get the first process.
It then traverses the process list . It opens each process with the
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
But somehow the OpenProcess is always failing.
Iam getting the following output.
Waiting on process for 20 seconds..
WARNING: OpenProcess failed with error 87 (The parameter is incorrect)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
WARNING: OpenProcess failed with error 5 (Access is denied)
Code:
#include <iostream>
using namespace std;
#include <Windows.h>
#include <tlhelp32.h>
//BOOL ListProcessThreads( DWORD dwOwnerPID );
//void printError( TCHAR const* msg );
#include <tchar.h>
#include <stdio.h>
// Forward declarations:
BOOL GetProcessList( DWORD cPid );
BOOL ListProcessModules( DWORD dwPID );
BOOL ListProcessThreads( DWORD dwOwnerPID );
void printError( TCHAR const* msg );
//int main( void )
//{
// GetProcessList( );
// return 0;
//}
int main ()
{
STARTUPINFO si = {};
si.cb = sizeof si;
PROCESS_INFORMATION pi = {};
const TCHAR* target = _T("C:\\Windows\\WinSxS\\wow64_microsoft-windows-calc_31bf3856ad364e35_10.0.19041.1_none_6a03b910ee7a4073\\calc.exe");
if ( !CreateProcess(target, 0, 0, FALSE, 0, 0, 0, 0, &si, &pi) )
{
cerr << "CreateProcess failed (" << GetLastError() << ").\n";
}
else
{
FILETIME ftime, fsys, fuser;
cout << "Waiting on process for 20 seconds.." << endl;
//ListProcessThreads(pi.hProcess);
//ListProcessThreads(GetCurrentProcessId() );
//ListProcessThreads(pi.dwProcessId);
WaitForSingleObject(pi.hProcess, 20 * 1000);
//GetProcessTimes(pi.hProcess, &ftime, &ftime, &fsys, &fuser);
GetProcessList(pi.dwProcessId);
/*
if ( TerminateProcess(pi.hProcess, 0) ) // Evil
cout << "Process terminated!";
*/
if ( PostThreadMessage(pi.dwThreadId, WM_QUIT, 0, 0) ) // Good
cout << "Request to terminate process has been sent!";
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
cin.sync();
cin.ignore();
return 0;
}
BOOL GetProcessList( DWORD cPid)
{
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
printError( TEXT("CreateToolhelp32Snapshot (of processes)") );
return( FALSE );
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof( PROCESSENTRY32 );
// Retrieve information about the first process,
// and exit if unsuccessful
if( !Process32First( hProcessSnap, &pe32 ) )
{
printError( TEXT("Process32First") ); // show cause of failure
CloseHandle( hProcessSnap ); // clean the snapshot object
return( FALSE );
}
// Now walk the snapshot of processes, and
// display information about each process in turn
do
{
//_tprintf( TEXT("\n\n=====================================================" ));
//_tprintf( TEXT("\nPROCESS NAME: %s"), pe32.szExeFile );
//_tprintf( TEXT("\n-------------------------------------------------------" ));
// Retrieve the priority class.
dwPriorityClass = 0;
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
if( hProcess == NULL )
printError( TEXT("OpenProcess") );
else
{
dwPriorityClass = GetPriorityClass( hProcess );
if( !dwPriorityClass )
printError( TEXT("GetPriorityClass") );
CloseHandle( hProcess );
}
if(cPid == pe32.th32ProcessID)
{
_tprintf( TEXT("\n Process ID = 0x%08X"), pe32.th32ProcessID );
_tprintf( TEXT("\n Thread count = %d"), pe32.cntThreads );
_tprintf( TEXT("\n Parent process ID = 0x%08X"), pe32.th32ParentProcessID );
_tprintf( TEXT("\n Priority base = %d"), pe32.pcPriClassBase );
if( dwPriorityClass )
_tprintf( TEXT("\n Priority class = %d"), dwPriorityClass );
// List the modules and threads associated with this process
ListProcessModules( pe32.th32ProcessID );
ListProcessThreads( pe32.th32ProcessID );
break;
}
} while( Process32Next( hProcessSnap, &pe32 ) );
CloseHandle( hProcessSnap );
return( TRUE );
}
BOOL ListProcessModules( DWORD dwPID )
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
// Take a snapshot of all modules in the specified process.
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
if( hModuleSnap == INVALID_HANDLE_VALUE )
{
printError( TEXT("CreateToolhelp32Snapshot (of modules)") );
return( FALSE );
}
// Set the size of the structure before using it.
me32.dwSize = sizeof( MODULEENTRY32 );
// Retrieve information about the first module,
// and exit if unsuccessful
if( !Module32First( hModuleSnap, &me32 ) )
{
printError( TEXT("Module32First") ); // show cause of failure
CloseHandle( hModuleSnap ); // clean the snapshot object
return( FALSE );
}
// Now walk the module list of the process,
// and display information about each module
do
{
_tprintf( TEXT("\n\n MODULE NAME: %s"), me32.szModule );
_tprintf( TEXT("\n Executable = %s"), me32.szExePath );
_tprintf( TEXT("\n Process ID = 0x%08X"), me32.th32ProcessID );
_tprintf( TEXT("\n Ref count (g) = 0x%04X"), me32.GlblcntUsage );
_tprintf( TEXT("\n Ref count (p) = 0x%04X"), me32.ProccntUsage );
_tprintf( TEXT("\n Base address = 0x%08X"), (DWORD) me32.modBaseAddr );
_tprintf( TEXT("\n Base size = %d"), me32.modBaseSize );
} while( Module32Next( hModuleSnap, &me32 ) );
CloseHandle( hModuleSnap );
return( TRUE );
}
BOOL ListProcessThreads( DWORD dwOwnerPID )
{
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
// Take a snapshot of all running threads
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( hThreadSnap == INVALID_HANDLE_VALUE )
return( FALSE );
// Fill in the size of the structure before using it.
te32.dwSize = sizeof(THREADENTRY32);
// Retrieve information about the first thread,
// and exit if unsuccessful
if( !Thread32First( hThreadSnap, &te32 ) )
{
printError( TEXT("Thread32First") ); // show cause of failure
CloseHandle( hThreadSnap ); // clean the snapshot object
return( FALSE );
}
// Now walk the thread list of the system,
// and display information about each thread
// associated with the specified process
do
{
if( te32.th32OwnerProcessID == dwOwnerPID )
{
_tprintf( TEXT("\n\n THREAD ID = 0x%08X"), te32.th32ThreadID );
_tprintf( TEXT("\n Base priority = %d"), te32.tpBasePri );
_tprintf( TEXT("\n Delta priority = %d"), te32.tpDeltaPri );
_tprintf( TEXT("\n"));
}
} while( Thread32Next(hThreadSnap, &te32 ) );
CloseHandle( hThreadSnap );
return( TRUE );
}
void printError( TCHAR const* msg )
{
DWORD eNum;
TCHAR sysMsg[256];
TCHAR* p;
eNum = GetLastError( );
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
sysMsg, 256, NULL );
// Trim the end of the line and terminate it with a null
p = sysMsg;
while( ( *p > 31 ) || ( *p == 9 ) )
++p;
do { *p-- = 0; } while( ( p >= sysMsg ) &&
( ( *p == '.' ) || ( *p < 33 ) ) );
// Display the message
_tprintf( TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg );
}
Last edited by pdk5; March 23rd, 2025 at 07:08 AM.
-
March 23rd, 2025, 11:54 AM
#2
Re: Process info display
PROCESS_ALL_ACCESS must be the cause of Access denied. The access level is way too high for an average app, so rejected. (See MSDN)
An option might be running your process with elevated privileges, but still requesting for a reasonable access level won't hurt anybody.
GetPriorityClass says:
The handle must have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right.
BTW, why don't you just cut that priority class stuff off?
Last edited by Igor Vartanov; March 23rd, 2025 at 12:15 PM.
Best regards,
Igor
-
March 25th, 2025, 04:00 AM
#3
Re: Process info display
Thankyou very much Igor. Sorry for delay, somehow the website was not reachable for me yesterday (!)
Im not windows internal programmer, so it would have been helpful with sample code. (Sorry for asking too much. Ofcourse, I'll try to do my homework)
-
March 25th, 2025, 05:13 AM
#4
Re: Process info display
Code:
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
For this to work, the process security descriptor for the requested process must allow this process the required access. This is not so by default. Or your process needs to have SeDebugPrivilege privilege - which requires admin access to set, You need to determine the minimum access security required for your program and open the process for that level of process access. If this is greater than the available process security then you're probably going to need SeDebugPrivilege and to run the program as an administrator.
GetPriorityClass() requires PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION privilege. So you should first try to acquire this privilege. See https://learn.microsoft.com/en-us/wi...ges-in-a-token
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
March 25th, 2025, 06:22 AM
#5
Re: Process info display
 Originally Posted by 2kaud
Code:
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
For this to work, the process security descriptor for the requested process must allow this process the required access. This is not so by default. Or your process needs to have SeDebugPrivilege privilege - which requires admin access to set, You need to determine the minimum access security required for your program and open the process for that level of process access. If this is greater than the available process security then you're probably going to need SeDebugPrivilege and to run the program as an administrator.
GetPriorityClass() requires PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION privilege. So you should first try to acquire this privilege. See https://learn.microsoft.com/en-us/wi...ges-in-a-token
Thankyou very much kaud for the help .I;ll go through the link.
But this app when the customer runs, they might not get the access (unless he runs in with high prio as admin). So I think, the logging functionality I am going to add, will only be enabled based on priority .
-
March 26th, 2025, 05:13 AM
#6
Re: Process info display
issues Im facing
1. Snapshot Process, does not show me the current process
2. If i open the process in the same function, the OpenProcess API succeeds. But fails in another function, where I try to acces process via a snapshot
In the BOOL GetProcessList( DWORD cPid), in the while loop, the none of the snapshot process ids match the one passed in.
Code:
int main ()
{
STARTUPINFO si = {};
si.cb = sizeof si;
PROCESS_INFORMATION pi = {};
const TCHAR* target = _T("C:\\Windows\\WinSxS\\wow64_microsoft-windows-calc_31bf3856ad364e35_10.0.19041.1_none_6a03b910ee7a4073\\calc.exe");
if ( !CreateProcess(target, 0, 0, FALSE, 0, 0, 0, 0, &si, &pi) )
{
cerr << "CreateProcess failed (" << GetLastError() << ").\n";
}
else
{
FILETIME ftime, fsys, fuser;
cout << "Waiting on process for 20 seconds.." << endl;
//ListProcessThreads(pi.hProcess);
//ListProcessThreads(GetCurrentProcessId() );
// This opens handle
HANDLE hProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_VM_OPERATION , NULL, pi.dwProcessId);
GetProcessList(pi.dwProcessId);
//
//ListProcessThreads(pi.dwProcessId);
WaitForSingleObject(pi.hProcess, 20 * 1000);
//HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId );
/*
if ( TerminateProcess(pi.hProcess, 0) ) // Evil
cout << "Process terminated!";
*/
if ( PostThreadMessage(pi.dwThreadId, WM_QUIT, 0, 0) ) // Good
cout << "Request to terminate process has been sent!";
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
cin.sync();
cin.ignore();
return 0;
}
BOOL GetProcessList( DWORD cPid)
{
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
// This open fails
hProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_VM_OPERATION , NULL, cPid);
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
printError( TEXT("CreateToolhelp32Snapshot (of processes)") );
return( FALSE );
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof( PROCESSENTRY32 );
// Retrieve information about the first process,
// and exit if unsuccessful
if( !Process32First( hProcessSnap, &pe32 ) )
{
printError( TEXT("Process32First") ); // show cause of failure
CloseHandle( hProcessSnap ); // clean the snapshot object
return( FALSE );
}
// Now walk the snapshot of processes, and
// display information about each process in turn
do
{
//_tprintf( TEXT("\n\n=====================================================" ));
//_tprintf( TEXT("\nPROCESS NAME: %s"), pe32.szExeFile );
//_tprintf( TEXT("\n-------------------------------------------------------" ));
// Retrieve the priority class.
dwPriorityClass = 0;
HANDLE hProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_VM_OPERATION , NULL, pe32.th32ProcessID);
//hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
if( hProcess == NULL )
printError( TEXT("OpenProcess") );
else
{
// Never hits this , ie snapshot doesnot have the current process
if(cPid == pe32.th32ProcessID)
{
_tprintf( TEXT("\n Process ID = 0x%08X"), pe32.th32ProcessID );
_tprintf( TEXT("\n Thread count = %d"), pe32.cntThreads );
_tprintf( TEXT("\n Parent process ID = 0x%08X"), pe32.th32ParentProcessID );
_tprintf( TEXT("\n Priority base = %d"), pe32.pcPriClassBase );
if( dwPriorityClass )
_tprintf( TEXT("\n Priority class = %d"), dwPriorityClass );
dwPriorityClass = GetPriorityClass( hProcess );
//if( !dwPriorityClass )
// printError( TEXT("GetPriorityClass") );
CloseHandle( hProcess );
break;
}
}
} while( Process32Next( hProcessSnap, &pe32 ) );
CloseHandle( hProcessSnap );
return( TRUE );
}
Eventhough for me, I used the snapshot of threads functionality to get the info, I wanted to know why this process snapshot doesnot work !
Last edited by pdk5; March 26th, 2025 at 05:16 AM.
-
March 26th, 2025, 06:48 AM
#7
Re: Process info display
When you call OpenProcess() you are not testing the return value for NULL. When you call ANY of the os api functions you need to always test for api failure. If an api call fails then you use GetLastError() to obtain the error code for the failure.
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
March 28th, 2025, 02:52 AM
#8
Re: Process info display
Thankyou very much kaud for inputs. OK I'll do that.
Btw, this I coded for my own understanding and I tried to check return via debugger (it was not NULL)
-
March 28th, 2025, 04:31 AM
#9
Re: Process info display
BTW, why are you trying to open the same process twice? and why try to open with PROCESS_VM_WRITE?
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
March 28th, 2025, 05:36 AM
#10
Re: Process info display
I'd suggest you first start small, get something working and then build on that with testing at each new stage. For a starter, this code will just enumerate all the processes:
Code:
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#include <Windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <stdio.h>
void printError(TCHAR const* msg);
BOOL DisplayProcesses();
int main() {
DisplayProcesses();
}
BOOL DisplayProcesses() {
// Take a snapshot of all processes in the system.
auto hProcessSnap { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };
if (hProcessSnap == INVALID_HANDLE_VALUE) {
printError(TEXT("CreateToolhelp32Snapshot (of processes)"));
return FALSE;
}
PROCESSENTRY32 pe32 { sizeof(PROCESSENTRY32) };
// Retrieve information about the first process,
// and exit if unsuccessful
if (!Process32First(hProcessSnap, &pe32)) {
printError(TEXT("Process32First")); // show cause of failure
CloseHandle(hProcessSnap); // clean the snapshot object
return(FALSE);
}
// Now walk the snapshot of processes, and
// display information about each process in turn
do {
_tprintf(TEXT("\n Process name = %s"), pe32.szExeFile);
_tprintf(TEXT("\n Process ID = 0x%08X"), pe32.th32ProcessID);
_tprintf(TEXT("\n Thread count = %d"), pe32.cntThreads);
_tprintf(TEXT("\n Parent process ID = 0x%08X"), pe32.th32ParentProcessID);
_tprintf(TEXT("\n Priority base = %d"), pe32.pcPriClassBase);
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return TRUE;
}
void printError(TCHAR const* msg) {
const auto eNum { GetLastError() };
TCHAR sysMsg[256];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
sysMsg, sizeof(sysMsg), NULL);
// Trim the end of the line and terminate it with a null
auto p { sysMsg };
while ((*p >= ' ') || (*p == 9))
++p;
do *p-- = 0;
while ((p >= sysMsg) && ((*p == '.') || (*p <= ' ')));
// Display the message
_tprintf(TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg);
}
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
March 28th, 2025, 08:20 AM
#11
Re: Process info display
This is an extension to the above code. This will start the program testc and then obtain process info about this program. Note that the program for which process data is to be obtained must not run and then terminate - otherwise it won't be picked up by the snapshot.
Code:
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#include <Windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <stdio.h>
void printError(TCHAR const* msg);
BOOL DisplayProcesses(DWORD pid = 0);
int main() {
const TCHAR* target { _T("C:\\myprogs\\testc.exe") };
STARTUPINFO si {sizeof(STARTUPINFO)};
PROCESS_INFORMATION pi {};
if (!CreateProcess(target, 0, 0, FALSE, 0, 0, 0, 0, &si, &pi))
return printError("CreateProcess failed"), 1;
const auto hProcess { OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_TERMINATE, NULL, pi.dwProcessId) };
if (hProcess != NULL) {
if (!DisplayProcesses(pi.dwProcessId))
_tprintf(TEXT("Process not found\n"));
if (TerminateProcess(hProcess, 0) == 0)
printError("TerminateProcess failed");
CloseHandle(hProcess);
} else
printError("OpenProcess failed");
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
BOOL DisplayProcesses(DWORD pid) {
// Take a snapshot of all processes in the system.
const auto hProcessSnap { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };
if (hProcessSnap == INVALID_HANDLE_VALUE) {
printError(TEXT("CreateToolhelp32Snapshot (of processes)"));
return FALSE;
}
PROCESSENTRY32 pe32 { sizeof(PROCESSENTRY32) };
// Retrieve information about the first process,
// and exit if unsuccessful
if (!Process32First(hProcessSnap, &pe32)) {
printError(TEXT("Process32First")); // show cause of failure
CloseHandle(hProcessSnap); // clean the snapshot object
return FALSE;
}
// Now walk the snapshot of processes, and
// display information about each process in turn
bool found {};
do
if ((pid == 0) || (pid == pe32.th32ProcessID)) {
_tprintf(TEXT("\n Process name = %s"), pe32.szExeFile);
_tprintf(TEXT("\n Process ID = 0x%08X"), pe32.th32ProcessID);
_tprintf(TEXT("\n Thread count = %d"), pe32.cntThreads);
_tprintf(TEXT("\n Parent process ID = 0x%08X"), pe32.th32ParentProcessID);
_tprintf(TEXT("\n Priority base = %d"), pe32.pcPriClassBase);
}
while ((pid == 0 || pid != pe32.th32ProcessID) && (found = Process32Next(hProcessSnap, &pe32)));
CloseHandle(hProcessSnap);
return (pid == 0 || found);
}
void printError(TCHAR const* msg) {
const auto eNum { GetLastError() };
TCHAR sysMsg[256];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
sysMsg, sizeof(sysMsg), NULL);
// Trim the end of the line and terminate it with a null
auto p { sysMsg };
while ((*p >= ' ') || (*p == 9))
++p;
do *p-- = 0;
while ((p >= sysMsg) && ((*p == '.') || (*p <= ' ')));
// Display the message
_tprintf(TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg);
}
Last edited by 2kaud; March 28th, 2025 at 08:23 AM.
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
March 29th, 2025, 08:36 AM
#12
Re: Process info display
Thankyou so much Kaud !!!. ie great help and highly appreciated. I always got so much support here.
-
March 29th, 2025, 11:23 AM
#13
Re: Process info display
I'm not sure what you're really trying to achieve - but do you know about sysinternals? Look at process monitor:
https://learn.microsoft.com/en-us/sy...nloads/procmon
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
March 30th, 2025, 04:30 AM
#14
Re: Process info display
Im basically wireless telecom software developer with c, and c++ coming from linux user level programming background (So not a systems programmer ). But wanted to add some logging for the new feature (which adds a process), to the legacy code. So wanted to study about that, before I add the logging.
Thanks a lot for the inputs, I'll look into the process monitor also
Btw, I also need to add a timer and wrote about issue in another thread, if you have any comments will be very helpful
(https://forums.codeguru.com/showthre...multithreading)
Last edited by pdk5; March 30th, 2025 at 04:48 AM.
-
April 7th, 2025, 11:06 AM
#15
Re: Process info display
Hello,
Ive finally comeup with the following solution for getting the information related to a process
1. Memory Usage (I reused existing code in the current code base)
2. CPU Utilisation (I got some info from the google)
3. Number of threads (I got this code from Microsoft reference code)
But the CPU utilisation value is coming bit too big. Not sure if it is related to any issue in the code.
Ive attached the o/p for reference
I need to find the number of process spawned by this process. Im thinking I can use the logic in step 3 (to check, if parent process id is same as current process)
.h
Code:
#include <thread>
#include <chrono>
#include <functional>
#include <cstdio>
#include <atomic>
#include <Pdh.h>
#include <PdhMsg.h>
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <processthreadsapi.h>
#include "psapi.h"
#include "string.h"
#include <ctime>
#include <tlhelp32.h>
using namespace std;
class ResourceUtilLoging
{
private:
ResourceUtilLoging()
{
SYSTEM_INFO sysInfo;
FILETIME ftime, fsys, fuser;
GetSystemInfo(&sysInfo);
m_nNumProcessors = sysInfo.dwNumberOfProcessors;
GetSystemTimeAsFileTime(&ftime);
memcpy(&m_nLastCpuUsage, &ftime, sizeof(FILETIME));
m_sProcessHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());
m_sProcessId = GetCurrentProcessId();
GetProcessTimes(m_sProcessHandle, &ftime, &ftime, &fsys, &fuser);
memcpy(&m_nLastCpuUsage, &fsys, sizeof(FILETIME));
memcpy(&m_nLastUserCpuUsage, &fuser, sizeof(FILETIME));
}
// TODOPRIYA: If needed, donot stop on destrucor, but on explict call to stop
~ResourceUtilLoging()
{
CloseHandle( m_sProcessHandle );
if (m_bRunning)
{
stopLog();
}
}
public:
static void DisplayLog();
static double getCurrentCPUValue()
{
FILETIME ftime, fsys, fuser;
ULARGE_INTEGER nNow, nSys, nUser;
double percent;
GetSystemTimeAsFileTime(&ftime);
memcpy(&nNow, &ftime, sizeof(FILETIME));
GetProcessTimes(m_sProcessHandle, &ftime, &ftime, &fsys, &fuser);
memcpy(&nSys, &fsys, sizeof(FILETIME));
memcpy(&nUser, &fuser, sizeof(FILETIME));
percent = (nSys.QuadPart - m_nLastSysCpuUsage.QuadPart) +
(nUser.QuadPart - m_nLastUserCpuUsage.QuadPart);
percent /= (nNow.QuadPart - m_nLastCpuUsage.QuadPart);
percent /= m_nNumProcessors;
m_nLastCpuUsage = nNow;
m_nLastUserCpuUsage = nUser;
m_nLastSysCpuUsage = nSys;
return percent * 100;
}
static BOOL ResourceUtilLoging::DisplayThreads();
static ResourceUtilLoging& getInstance()
{
static ResourceUtilLoging theInstance;
return theInstance;
}
typedef std::chrono::milliseconds Interval;
typedef std::function<void()> Timeout;
void startLog(const Interval &interval, const Timeout &timeout, string sFileName)
{
m_sLogFileName = sFileName;
m_bRunning = true;
m_sThread = std::thread([this, interval, timeout]
{
while (m_bRunning)
{
std::this_thread::sleep_for(interval);
timeout();
}
});
}
void stopLog()
{
m_bRunning = false;
m_sThread.join();
}
static std::thread m_sThread;
static std::atomic_bool m_bRunning;
static std::string m_sLogFileName;
static ULARGE_INTEGER m_nLastCpuUsage, m_nLastSysCpuUsage, m_nLastUserCpuUsage;
static int m_nNumProcessors;
static HANDLE m_sProcessHandle;
static DWORD m_sProcessId;
static long long m_nPhysMemUsedByMePrevious;
};
//static PDH_HQUERY cpuQuery;
//static PDH_HCOUNTER cpuTotal;
//void init()
//{
// PDH_STATUS a = PdhOpenQuery(NULL, NULL, &cpuQuery);
// PDH_STATUS i = PdhAddEnglishCounter(cpuQuery, L"\\Processor(_Total)\\% Processor Time", NULL, &cpuTotal);
// PdhCollectQueryData(cpuQuery);
//}
//
//double getCurrentValue()
//{
// init();
// PDH_FMT_COUNTERVALUE counterVal;
//
// PdhCollectQueryData(cpuQuery);
// PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
// return counterVal.doubleValue;
//}
.cpp
Code:
#include "ResourceUtilLoging.h"
std::thread ResourceUtilLoging::m_sThread{};
std::atomic_bool ResourceUtilLoging::m_bRunning{};
ULARGE_INTEGER ResourceUtilLoging::m_nLastCpuUsage{}, ResourceUtilLoging::m_nLastSysCpuUsage{}, ResourceUtilLoging::m_nLastUserCpuUsage{};
int ResourceUtilLoging::m_nNumProcessors{};
HANDLE ResourceUtilLoging::m_sProcessHandle{};
DWORD ResourceUtilLoging::m_sProcessId{};
long long ResourceUtilLoging::m_nPhysMemUsedByMePrevious;
std::string ResourceUtilLoging::m_sLogFileName;
void ResourceUtilLoging::DisplayLog()
{
std::ofstream myfile(m_sLogFileName, std::ios::app);
myfile.setf(std::ios::fixed, std::ios::floatfield);
myfile.precision(3);
time_t now = time(0);
char dt[ 50 ];
std::time_t t = std::time( NULL );
errno_t e = ctime_s( dt, 50, &t );
//if (e) std::cout << "err!\n";
//else std::cout << dt;
myfile << endl << string(dt);
double dCPUUsage = ResourceUtilLoging::getCurrentCPUValue();
// Now log the CPU Usage for this process
if (myfile.is_open())
{
myfile << "CPU Usgae : " << dCPUUsage << "\n";
}
long long delta;
// Now Log the Memory Usage for this process
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&memInfo);
DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile;
DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile;
DWORDLONG totalPhysMem = memInfo.ullTotalPhys;
DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;
PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;
SIZE_T physMemUsedByMe = pmc.WorkingSetSize;
delta = (long long) physMemUsedByMe - m_nPhysMemUsedByMePrevious;
myfile << "Process RAM current: " << std::to_string(physMemUsedByMe / 1E9) << " GB, Delta:" << (std::to_string( delta / 1E6)).append(" MB ") << std::endl;
//message.append(" process RAM current:").append(std::to_string(physMemUsedByMe / 1E9)).append(" GB");
m_nPhysMemUsedByMePrevious = (long long) physMemUsedByMe;
// Display the Thread count of the current process
DisplayThreads();
}
BOOL ResourceUtilLoging::DisplayThreads()
{
std::ofstream myfile(m_sLogFileName, std::ios::app);
myfile.setf(std::ios::fixed, std::ios::floatfield);
myfile.precision(3);
time_t now = time(0);
// Take a snapshot of all processes in the system.
const auto hProcessSnap { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };
if (hProcessSnap == INVALID_HANDLE_VALUE) {
//printError(TEXT("CreateToolhelp32Snapshot (of processes)"));
return FALSE;
}
PROCESSENTRY32 pe32 { sizeof(PROCESSENTRY32) };
// Retrieve information about the first process,
// and exit if unsuccessful
if (!Process32First(hProcessSnap, &pe32)) {
//printError(TEXT("Process32First")); // show cause of failure
CloseHandle(hProcessSnap); // clean the snapshot object
return FALSE;
}
// Now walk the snapshot of processes, and
// display information about each process in turn
bool found {};
do
if ((m_sProcessId == 0) || (m_sProcessId == pe32.th32ProcessID))
{
//_tprintf(TEXT("\n Process name = %s"), pe32.szExeFile);
//_tprintf(TEXT("\n Process ID = 0x%08X"), pe32.th32ProcessID);
//_tprintf(TEXT("\n Thread count = %d"), pe32.cntThreads);
//_tprintf(TEXT("\n Parent process ID = 0x%08X"), pe32.th32ParentProcessID);
//_tprintf(TEXT("\n Priority base = %d"), pe32.pcPriClassBase);
myfile << "Process Thread Current: : " << std::to_string(pe32.cntThreads) << endl;
}
while ((m_sProcessId == 0 || m_sProcessId != pe32.th32ProcessID) && (found = Process32Next(hProcessSnap, &pe32)));
CloseHandle(hProcessSnap);
return (m_sProcessId == 0 || found);
}
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|