Process Management in C++

Click the above“Mechanical and Electronic Engineering Technology” to follow us
A process is a running activity of a program regarding a set of data in a computer. It is the basic unit for resource allocation in the system and the foundation of the operating system structure. It is the basic unit of dynamic execution in the operating system, and in traditional operating systems, a process is both the basic unit of allocation and the basic unit of execution.
From a theoretical perspective, a process is an abstraction of a running program’s execution; from an implementation perspective, a process is a data structure aimed at clearly depicting the inherent laws of dynamic systems and effectively managing and scheduling programs running in the main memory of the computer system.
A process is dynamic; it is created and terminated dynamically. Each process has its own address space, including the text area, data area, and stack. The text area stores the code executed by the processor; the data area stores variables and dynamically allocated memory used during the process execution; the stack area stores the instructions and local variables of the active process calls.
There is a fundamental difference between a process and a program. A program is an ordered collection of instructions and data, which has no meaning of execution itself; it is a static concept. A process is an execution of a program on the processor; it is a dynamic concept with a certain lifespan. Programs are permanent, while processes are temporary. Processes can better describe concurrency, while programs cannot. Additionally, processes have the capability to create other processes, whereas programs do not. The same program running on several sets of data will belong to several different processes, meaning that the same program can correspond to multiple processes.

1. Creating a Process

In C++, creating a Windows process typically involves using Windows API functions, particularly the CreateProcess function. This function allows you to start a new process and its main thread and specify the command line, initial window state, environment block, etc. for the new process.
Here is a simple example demonstrating how to use the CreateProcess function to create a new Windows process:
#include <windows.h>  #include <tchar.h>  #include <iostream>  
int main() {    STARTUPINFO si;    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));    si.cb = sizeof(si);    ZeroMemory(&pi, sizeof(pi));
    // Set command line parameters, here using notepad.exe as an example      TCHAR cmdLine[] = _T("C:\Windows\System32\notepad.exe");
    // Create process      if (!CreateProcess(NULL,   // Not using module name          cmdLine,        // Command line          NULL,           // Process handle not inheritable          NULL,           // Thread handle not inheritable          FALSE,          // Set handle inheritance flag          0,              // No creation flags          NULL,           // Use parent's environment block          NULL,           // Use parent's drive and directory          &si,            // Pointer to STARTUPINFO structure          &pi)           // Pointer to PROCESS_INFORMATION structure          ) {        std::cerr << "CreateProcess failed (" << GetLastError() << ")." << std::endl;        return 1;    }
    // Wait for the process to finish so we can see the notepad window      WaitForSingleObject(pi.hProcess, INFINITE);
    // Close process and thread handles      CloseHandle(pi.hProcess);    CloseHandle(pi.hThread);
    return 0;}

2. Getting the PID of a Specific Process

In C++, obtaining the PID (Process Identifier) of a Windows process usually involves using Windows API functions to enumerate the processes in the system and checking each process’s name or other properties to determine the desired PID. A commonly used function is Toolhelp32Snapshot, which allows you to get a snapshot containing information about all processes currently in the system.
Here is a simple example demonstrating how to use Toolhelp32Snapshot and PROCESSENTRY32 structure to get the PID of a specific process name:
#include <windows.h>  #include <tlhelp32.h>  #include <iostream>  #include <string>  
DWORD GetProcessIdByName(const std::wstring& processName) {    DWORD pid = 0;    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);    if (hSnapshot != INVALID_HANDLE_VALUE) {        PROCESSENTRY32 pe32;        pe32.dwSize = sizeof(PROCESSENTRY32);        if (Process32First(hSnapshot, &pe32)) {            do {                if (std::wstring(pe32.szExeFile) == processName) {                    pid = pe32.th32ProcessID;                    break;                }            } while (Process32Next(hSnapshot, &pe32));        }        CloseHandle(hSnapshot);    }    return pid;}
int main() {    std::wstring processName = L"notepad.exe"; // Process name to find      DWORD pid = GetProcessIdByName(processName);    if (pid != 0) {        std::wcout << L"Process ID for " << processName << L" is: " << pid << std::endl;    }    else {        std::wcout << L"Process not found." << std::endl;    }    return 0;}

Process ID for notepad.exe is: 9428

3. Terminating a Process

Terminating a process in a computer operating system refers to closing or ending a running program or process. When multiple programs and processes are running simultaneously in the system, the operating system provides tools and methods to terminate unnecessary or problematic processes to control and manage these processes. The purpose of terminating a process is usually to resolve the following issues:
Excessive Resource Usage: A process may consume excessive CPU, memory, or disk resources due to anomalies or errors, preventing other processes from running normally. In this case, you can choose to terminate the process to free up resources and fix the issue.
Slow or Unresponsive: A process may become unresponsive for an extended period due to deadlocks, infinite loops, or other reasons, preventing user interaction or blocking other processes. Terminating the process can restore normal system operation.
Dangerous or Malicious Programs: Some programs may exhibit dangerous or malicious behavior, such as viruses, malware, or unauthorized access. In this case, terminating the process can prevent further damage to the system.
In C++, closing a Windows process typically involves using Windows API functions, such as TerminateProcess, or sending specific signals to the process to request its graceful shutdown. However, a more common and recommended approach is to allow the process to handle the shutdown logic itself, if possible, by receiving an exit signal or calling a specific shutdown function.
If you indeed need to close a process from the outside, you can use the TerminateProcess function. This function will immediately terminate the specified process and all its threads. Here is a simple example:
#include <windows.h>  #include <tlhelp32.h>  #include <iostream>  
bool CloseProcessByPID(DWORD pid) {    HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid);    if (hProcess == NULL) {        std::cerr << "OpenProcess failed (" << GetLastError() << ")." << std::endl;        return false;    }
    if (!TerminateProcess(hProcess, 999)) { // 999 is the exit code, can be customized          std::cerr << "TerminateProcess failed (" << GetLastError() << ")." << std::endl;        CloseHandle(hProcess);        return false;    }
    CloseHandle(hProcess);    return true;}
int main() {    DWORD pid = 9428; // Replace with the PID of the process you want to close      if (CloseProcessByPID(pid)) {        std::cout << "Process with PID " << pid << " has been terminated." << std::endl;    }    else {        std::cout << "Failed to terminate process with PID " << pid << "." << std::endl;    }    return 0;}

Process with PID 9428 has been terminated.

4. Enumerating Processes

In C++, enumerating Windows processes typically involves using Windows API functions to obtain a list of all currently running processes in the system. The CreateToolhelp32Snapshot function is a commonly used method to accomplish this task, allowing you to create a snapshot containing the system’s state information, such as running processes.
Here is an example code using CreateToolhelp32Snapshot and PROCESSENTRY32 structure to enumerate Windows processes:
#include <windows.h>  #include <tlhelp32.h>  #include <iostream>  #include <vector>  
bool EnumerateProcesses(std::vector<DWORD>& processIds) {    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);    if (hSnapshot == INVALID_HANDLE_VALUE) {        return false;    }
    PROCESSENTRY32 pe32;    pe32.dwSize = sizeof(PROCESSENTRY32);    if (!Process32First(hSnapshot, &pe32)) {        CloseHandle(hSnapshot);        return false;    }
    do {        processIds.push_back(pe32.th32ProcessID);    } while (Process32Next(hSnapshot, &pe32));
    CloseHandle(hSnapshot);    return true;}
int main() {    std::vector<DWORD> processIds;    if (EnumerateProcesses(processIds)) {        std::cout << "Enumerated processes:\n";        for (const auto pid : processIds) {            std::cout << "PID: " << pid << std::endl;        }    }    else {        std::cerr << "Failed to enumerate processes." << std::endl;    }    return 0;}

Enumerated processes:

PID: 0

PID: 4

PID: 100

PID: 432

PID: 704

PID: 808

PID: 832

PID: 904

PID: 912

Process Management in C++

Want to learn more

Quickly scan the code to follow

Leave a Comment