Get process memory information - c++

I've been trying to get process memory information in windows, and I've been following Microsoft docs and I've got this code but it
doesn't seem to work. It is supposed to print succeeded, but it doesn't print anything at all. My debugging tells me its because hProcess = null,
but i don't understand why. Here is my current code
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
#include<iostream>
using namespace std;
int main()
{
DWORD aProcesses[1024], cbNeeded, cProcesses;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
{
return 1;
}
cProcesses = cbNeeded / sizeof(DWORD);
for (int i = 0; i < cProcesses; i++ )
{
int processID = aProcesses[i];
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
if (NULL == hProcess)
return 2;
if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
{
cout<<"SUCCEEDED";
}
CloseHandle( hProcess );
}
return 0;
}

You probably don't have permission to read memory of certain (privileged system) processes. Check GetLastError if you get a NULL handle back from OpenProcess.
In general checking and handling Win32 error conditions is a good practice, even if the API 'usually' works for you.

Related

Is there a way to list every windows processes from cpp?

I'm recently looking to list every processes of a machine to do some action. But I'm struggling with processes which are not launched from my user (eg: system, administrator or an other user).
I tried some codes and some solutions but there is still anything who works.
I am working on the code proposed by microsoft to enumerate all the processes.
Here is the code :
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <psapi.h>
// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
// and compile with -DPSAPI_VERSION=1
void PrintProcessNameAndID( DWORD processID )
{
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
// Get a handle to the process.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
// Get the process name.
if (NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
&cbNeeded) )
{
GetModuleBaseName( hProcess, hMod, szProcessName,
sizeof(szProcessName)/sizeof(TCHAR) );
}
}
// Print the process name and identifier.
_tprintf( TEXT("%s (PID: %u)\n"), szProcessName, processID );
// Release the handle to the process.
CloseHandle( hProcess );
}
int main( void )
{
// Get the list of process identifiers.
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
{
return 1;
}
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the name and process identifier for each process.
for ( i = 0; i < cProcesses; i++ )
{
if( aProcesses[i] != 0 )
{
PrintProcessNameAndID( aProcesses[i] );
}
}
return 0;
}
This code works but does not allow you to view the processes of other users. Do you have an idea?
Thanks everyone for your time.
Regards
As a normal user, you are not going to get far by using OpenProcess on processes you don't own. If you elevate your process and enable the debug privilege you might have more luck. You will probably still be denied access to DRM and AntiVirus processes. In general the PSAPI functions expect a lot of access to the process with PROCESS_VM_READ being the biggest issue, Windows is not going to grant you memory read access to all other processes. Some of the newer APIs like GetProcessImageFileName have been upgraded (in Vista+) to only require PROCESS_QUERY_LIMITED_INFORMATION which you might be able to get for more processes.
I would suggest using the Toolhelp API instead, it should provide a little more info than EnumProcesses+OpenProcess. You can also get some information from the Performance Counters and WMI.
As a side note; EnumProcesses is the most useless API ever. It uses the NT API to get information about all processes then throws away all that information except the process ids.
If you are willing to use undocumented stuff, the NT Query/Information functions will give you more information than any documented API.
The most reasonable solution I think would be to use
CreateToolhelp32Snapshot
You can do some looking up on it at https://learn.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot
Heres a small example
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
std::cout << "CreateToolhelp32Snapshot (of processes) failed with error " << GetLastError() << std::endl;
return;
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcessSnap, &pe32))
{
std::cout << "Failed getting first process" << std::endl;
CloseHandle(hProcessSnap);
return;
}
do
{
std::cout << "Process: " << pe32.szExeFile << std::endl;
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);

How to determine an application is already launched or not in windows using C++?

I am launching an windows desktop application by
CATStartProcess (const char *comPath,
char *const argv[],
int wait, int *pid,
int *exitStatus);
The arguments are passed to it.
If the application is already running I don't need to create a new instance for this. How can I check if this application is already running in background or not?
int wait = 0;
int pid;
int exitStatus;
char *CommandArgs[9] = { 0 };
CommandArgs[0] = (char*)usComposerExePath.ConvertToChar();
CommandArgs[1] = (char*)usOpen.ConvertToChar();
CommandArgs[2] = (char*)usComposerProjectDocPath.ConvertToChar();
CommandArgs[3] = (char*)strInfiniteTicket.ConvertToChar();
CommandArgs[4] = (char*)strDocName.ConvertToChar();
CommandArgs[5] = (char*)strSecurityContext.ConvertToChar();
CommandArgs[6] = (char*)usBusID.ConvertToChar();
CommandArgs[7] = (char*)usUserID.ConvertToChar();
CommandArgs[8] = NULL;
CATLibStatus startComposerBatchStatus = CATStartProcess((char*)usComposerExePath.ConvertToChar(), CommandArgs, wait, &pid, &exitStatus);
There's a few ways, but I'll admit, neither of my two solutions are portable/standard C++, but you tagged Windows, so I'll give a Windows method.
The below code actually performs both checks. The first method is to use a named mutex. Windows has a "Global" mutex, which checks for running processes by any user. If the mutex already exists, then its running. If it doesn't exist, then it's not running. There's some states where things can't be easily determined, so it checks the running process list. This part is less accurate, since different permissions affects the list.
The part with mutexes will only work if you can modify the application you are trying to launch so that it creates a mutex.
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <psapi.h>
#include <TlHelp32.h>
#include <shellapi.h>
#include <advpub.h>
enum class ProcessRunningState {
YES,
NO,
ERR
};
ProcessRunningState CheckIfProcessIsAlreadyRunning( DWORD currentProcessId, const wchar_t *programName, const wchar_t *programGUID, HANDLE *mutex_handle ) noexcept {
{ // Check the mutexes first
wchar_t global_prog_name[1024] = L"Global\\";
wcsncat_s( global_prog_name, programName, wcslen( programGUID ) );
if ( mutex_handle ) {
*mutex_handle = CreateMutex( NULL, TRUE, global_prog_name );
if ( !( *mutex_handle ) ) {
const DWORD dw = GetLastError();
if ( dw == ERROR_ALREADY_EXISTS )
return ProcessRunningState::YES;
} else {
return ProcessRunningState::NO;
}
} else {
HANDLE h = OpenMutex( SYNCHRONIZE, FALSE, global_prog_name );
if ( h ) {
CloseHandle( h );
return ProcessRunningState::YES;
} else if ( GetLastError() == ERROR_FILE_NOT_FOUND ) {
return ProcessRunningState::NO;
}
}
}
{ // At this point, the state is unknown, so try running through the process list
DWORD aProcesses[2048], cProcesses;
if ( !EnumProcesses( aProcesses, sizeof( aProcesses ), &cProcesses ) ) {
return ProcessRunningState::ERR;
}
// Calculate how many process identifiers were returned.
cProcesses = cProcesses / sizeof( DWORD );
for ( unsigned int i = 0; i < cProcesses; i++ ) {
if ( aProcesses[i] != 0 && aProcesses[i] != currentProcessId ) {
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] );
WCHAR szProcessName[MAX_PATH] = { 0 };
if ( hProcess ) {
HMODULE hMod;
DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof( hMod ), &cbNeeded ) ) {
GetModuleBaseName( hProcess, hMod, szProcessName, sizeof( szProcessName ) / sizeof( TCHAR ) ); // Can't error here, since this function "errors" on access
}/* else {
return ProcessRunningState::ERR;
}*/
CloseHandle( hProcess );
}
if ( _wcsicmp( szProcessName, programName ) == 0 ) {
return ProcessRunningState::YES;
}
}
}
}
return ProcessRunningState::NO;
}
Calling it like so will create the mutex if possible, and basically says that "I want to run, can I?"
HANDLE mutex_handle;
const ProcessRunningState cur_state = CheckIfProcessIsAlreadyRunning( GetCurrentProcessId(), L"PROGRAM_NAME", programGUID, &mutex_handle );
switch ( cur_state ) {
case ProcessRunningState::ERR:
case ProcessRunningState::YES:
return ERROR_ALREADY_EXISTS;
default:
break;
}
Calling it like so, simply checks if its already running, and launches the application if not.
if ( CheckIfProcessIsAlreadyRunning( GetCurrentProcessId(), L"PROGRAM_NAME", programGUID, nullptr ) == ProcessRunningState::NO ) {
std::wstring programInstallLocation = L"path";
std::wstring programName = programInstallLocation + L"\\PROGRAM_NAME";
ShellExecute( NULL, L"open", programName.c_str(), NULL, NULL, SW_SHOW );
}
And somewhere in your code, you would specify what programGUID is. For example:
WCHAR programGUID[] = L"ba2e95a0-9168-4b6e-bcd6-57309748df21";

windows EnumProcesses some process names as <unknown>

Hello I have this sample code running which uses x to print processNames and PIDS of all currently running processes. Only some of them display an actual name though, with others displaying as (as seen in my output image below)
I was wondering if this was expected behavior, and that not all processes have a name (I could see this being the case for minimal background processes), or if I was using the EnumProcesses function incorrectly.
My code is:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <tchar.h>
//https://learn.microsoft.com/en-us/windows/desktop/psapi/enumerating-all-processes
void PrintProcessNameAndID( DWORD processID ){
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
// Get a handle to the process.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
// Get the process name.
if (NULL != hProcess ){
HMODULE hMod;
DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) ){
GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR) );
}
}
// Print the process name and identifier.
_tprintf( TEXT("%s (PID: %u)\n"), szProcessName, processID );
// Release the handle to the process.
CloseHandle( hProcess );
}
//https://learn.microsoft.com/en-us/windows/desktop/psapi/enumerating-all-processes
int main( void ){
// Get the list of process identifiers.
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ){
return 1;
}
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the name and process identifier for each process.
//for ( i = 0; i < cProcesses; i++ ){
for ( i = 0; i < 3; i++ ){
if( aProcesses[i] != 0 ) {
_tprintf( TEXT("aProcesses[%u] = %u (process ID)\n"), i, aProcesses[i] );
PrintProcessNameAndID( aProcesses[i] );
ListProcessThreads( aProcesses[i] );
}
}
return 0;
}
As stated in documentation, OpenProcess fails for idle and CSRSS processes.
If the specified process is the Idle process or one of the CSRSS
processes, this function fails and the last error code is
ERROR_ACCESS_DENIED because their access restrictions prevent
user-level code from opening them.
You have to enable SeDebugPrivilege (and also run your application with admin privileges). Moreover, if your application is compiled as 32-bit, it cannot access 64-bit processes with OpenProcess
If you just want a list of running processes, use CreateToolhelp32Snapshot to list running processes.
#define UNICODE
#include <Windows.h>
#include <stdio.h>
#include <psapi.h>
#include <tlhelp32.h>
int main()
{
wprintf(L"Start:\n");
HANDLE hndl = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPMODULE, 0);
if(hndl)
{
PROCESSENTRY32 process = { sizeof(PROCESSENTRY32) };
Process32First(hndl, &process);
do
{
wprintf(L"%8u, %s\n", process.th32ProcessID, process.szExeFile);
} while(Process32Next(hndl, &process));
CloseHandle(hndl);
}
}
Side note, it is recommended to compile the program as Unicode. Avoid _txxx macros such as _tprintf etc.

C++ iterate processes and find out command line args of each process

I have the following problem to solve (VS2012, C++)
I have to find out if a specific HTA app is running from my exe. For that, I have to find the process mshta and check if it has correct arguments (should have been started as "mshta somehta.hta"). My first attempt was to iterate over the processes/modules, which I can do now. I see mshta listed and its PID. But, I did not find the way to get the info, how it was started. Is there a way to do it?
ProcessExists(wchar_t* processName)
{
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
{
return false;
}
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the name and process identifier for each process.
for ( i = 0; i < cProcesses; i++ )
{
if( aProcesses[i] != 0 )
{
PrintProcessNameAndID( aProcesses[i] );
}
}
return false;
}
void PrintProcessNameAndID( DWORD processID )
{
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
// Get a handle to the process.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
// Get the process name.
if (NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
&cbNeeded) )
{
GetModuleBaseName( hProcess, hMod, szProcessName,
sizeof(szProcessName)/sizeof(TCHAR) );
}
}
// Print the process name and identifier.
dprintf( TEXT("%s (PID: %u) %s %s\n"), szProcessName, processID );
// Release the handle to the process.
CloseHandle( hProcess );
}
I ended up to use the solution proposed here: http://www.codeproject.com/Articles/19685/Get-Process-Info-with-NtQueryInformationProcess

How to effectively kill a process in C++ (Win32)?

I am currently writing a very lightweight program so I have to use C++ since it is not bound to .NET framework which drastically increases size of the program.
I need to be able to terminate process and to do that I need to get a process handle. Unfortuanately I haven't figured how to do that yet.
P.S. I know that to kill a process you have to use TerminateProcess.
The following code works:
const auto explorer = OpenProcess(PROCESS_TERMINATE, false, process_id);
TerminateProcess(explorer, 1);
CloseHandle(explorer);
The PID you need for OpenProcess() is not normally easy to get a hold of. If all you got is a process name then you need to iterate the running processes on the machine. Do so with CreateToolhelp32Snapshot, followed by Process32First and loop with Process32Next. The PROCESSENTRY32.szExeFile gives you the process name (not path!), th32ProcessID gives you the PID.
The next consideration is that the process may appear more than once. And there's a chance that the same process name is used for very different programs. Like "Setup". If you don't just want to kill them all, you'll need to try to obtain some runtime info from them. Window caption bar text, perhaps. GetProcessImageFileName() can give you the path to the .exe. It uses the native kernel format, you'd need QueryDosDevice to map a disk drive device name to a drive letter.
The next consideration is the rights you ask for in OpenProcess(). You are unlikely to get PROCESS_ALL_ACCESS, all you need is PROCESS_TERMINATE. Although that's privileged as well. Ensure the account you use to run your program can obtain that right.
Rather than going through all that pain to kill a process with a known name, why not simply call out to "system" and ask the command-line to kill it?
For example,
int retval = ::_tsystem( _T("taskkill /F /T /IM MyProcess.exe") );
To get a handle to pass to TerminateProcess, use OpenProcess in combination with some other function like EnumProcesses.
Here is the full example for Visual Studio 2010 C++ project how to kill the process by the EXE file name.
In order to check it just run Internet Explorer and after this execute following code.
#include <iostream>
#include <string>
#include<tchar.h>
#include <process.h>
#include <windows.h>
#include <tlhelp32.h>
using namespace std;
// Forward declarations:
BOOL GetProcessList();
BOOL TerminateMyProcess(DWORD dwProcessId, UINT uExitCode);
int main( void )
{
GetProcessList( );
return 0;
}
BOOL GetProcessList( )
{
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 )
{
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 ) )
{
CloseHandle( hProcessSnap ); // clean the snapshot object
return( FALSE );
}
// Now walk the snapshot of processes
do
{
string str(pe32.szExeFile);
if(str == "iexplore.exe") // put the name of your process you want to kill
{
TerminateMyProcess(pe32.th32ProcessID, 1);
}
} while( Process32Next( hProcessSnap, &pe32 ) );
CloseHandle( hProcessSnap );
return( TRUE );
}
BOOL TerminateMyProcess(DWORD dwProcessId, UINT uExitCode)
{
DWORD dwDesiredAccess = PROCESS_TERMINATE;
BOOL bInheritHandle = FALSE;
HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
if (hProcess == NULL)
return FALSE;
BOOL result = TerminateProcess(hProcess, uExitCode);
CloseHandle(hProcess);
return result;
}
Imagine in C# it looks like
using System;
using System.Collections.Generic;
using System.Text;
namespace MyProcessKiller
{
class Program
{
static void Main(string[] args)
{
foreach (System.Diagnostics.Process myProc in System.Diagnostics.Process.GetProcesses())
{
if (myProc.ProcessName == "iexplore")
{
myProc.Kill();
}
}
}
}
}
windows only
system("taskkill /f /im servicetokill.exe")
Here are some working sample codes to kill a process called "ShouldBeDead.exe":
// you will need these headers, and you also need to link to Psapi.lib
#include <tchar.h>
#include <psapi.h>
...
// first get all the process so that we can get the process id
DWORD processes[1024], count;
if( !EnumProcesses( processes, sizeof(processes), &count ) )
{
return false;
}
count /= sizeof(DWORD);
for(unsigned int i = 0; i < count; i++)
{
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
if(processes[i] != 0)
{
// remember to open with PROCESS_ALL_ACCESS, otherwise you will not be able to kill it
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, processes[i] );
if(NULL != hProcess)
{
HMODULE hMod;
DWORD cbNeeded;
if(EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
{
GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR));
// find the process and kill it
if(strcmp(szProcessName, "ShouldBeDead.exe") == 0)
{
DWORD result = WAIT_OBJECT_0;
while(result == WAIT_OBJECT_0)
{
// use WaitForSingleObject to make sure it's dead
result = WaitForSingleObject(hProcess, 100);
TerminateProcess(hProcess, 0);
}
CloseHandle(hProcess);
}
}
}
}
}
CreateProcess and OpenProcess return process handles.
Here's some sample code to find a process by asking the system to list all processes and then searching the list for the process you want.
Task Killer using Modern C++
Below is the code I've created for my Terminator Program
//_____________________________________________
// |
// TheNexGen of Terminator (inclusion version) |
// ------------------------------------------- |
// |
// Add your Programs in the 'if' check as I've |
// listed below, and compile using c++17 flag |
// or higher |
//_____________________________________________|
#include <process.h>
#include <windows.h>
#include <tlhelp32.h>
#include <string_view>
using namespace std;
int main()
{
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE) return 0;
PROCESSENTRY32W pe32{ .dwSize = sizeof(PROCESSENTRY32) };
if (!Process32First(hProcessSnap, &pe32)) return CloseHandle(hProcessSnap), 0;
do
{
wstring_view str = pe32.szExeFile;
if
(
str == L"chrome.exe"
|| str == L"AAM Update Notifier.exe"
|| str == L"About.exe"
|| str == L"ActionCenterDownloader.exe"
|| str == L"adb.exe"
|| str == L"AdobeARM.exe"
)
{
if (HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0, pe32.th32ProcessID))
{
TerminateProcess(hProcess, 1);
CloseHandle(hProcess);
}
}
}
while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
}
Description
Increased Execution Speed 100x of the Code provided by #DmitryBoyko.