Skip to content

Commit 71e8585

Browse files
authored
Create winreaper.cpp
1 parent bcf11d0 commit 71e8585

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

winreaper.cpp

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#include <windows.h>
2+
#include <iostream>
3+
#include <tlhelp32.h>
4+
#include <string>
5+
#include <vector>
6+
#include <memory>
7+
#include <set>
8+
#include <chrono>
9+
#include <thread>
10+
11+
std::wstring getProcessName(DWORD pid) {
12+
PROCESSENTRY32 entry;
13+
entry.dwSize = sizeof(PROCESSENTRY32);
14+
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
15+
16+
if (hSnapshot == INVALID_HANDLE_VALUE) {
17+
std::wcerr << L"Failed to take process snapshot: " << GetLastError() << L"\n";
18+
return L"Unknown";
19+
}
20+
21+
if (Process32First(hSnapshot, &entry)) {
22+
do {
23+
if (entry.th32ProcessID == pid) {
24+
CloseHandle(hSnapshot);
25+
return entry.szExeFile;
26+
}
27+
} while (Process32Next(hSnapshot, &entry));
28+
}
29+
30+
CloseHandle(hSnapshot);
31+
return L"Unknown";
32+
}
33+
34+
void waitForProcess(DWORD pid) {
35+
HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, pid);
36+
if (hProcess == NULL) {
37+
std::wcerr << L"Failed to open process with PID " << pid << L": " << GetLastError() << L"\n";
38+
return;
39+
}
40+
41+
// Wait for the process to finish
42+
WaitForSingleObject(hProcess, INFINITE);
43+
CloseHandle(hProcess);
44+
}
45+
46+
std::vector<DWORD> getChildProcesses(DWORD parentPid) {
47+
std::vector<DWORD> childPids;
48+
PROCESSENTRY32 entry;
49+
entry.dwSize = sizeof(PROCESSENTRY32);
50+
51+
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
52+
if (hSnapshot == INVALID_HANDLE_VALUE) {
53+
std::wcerr << L"Failed to take process snapshot: " << GetLastError() << L"\n";
54+
return childPids;
55+
}
56+
57+
if (Process32First(hSnapshot, &entry)) {
58+
do {
59+
if (entry.th32ParentProcessID == parentPid) {
60+
childPids.push_back(entry.th32ProcessID);
61+
}
62+
} while (Process32Next(hSnapshot, &entry));
63+
}
64+
CloseHandle(hSnapshot);
65+
66+
return childPids;
67+
}
68+
69+
void logProcessStatus(const std::set<DWORD>& previousPids, const std::set<DWORD>& currentPids) {
70+
for (DWORD pid : previousPids) {
71+
if (currentPids.find(pid) == currentPids.end()) {
72+
std::wcout << L"Process with PID " << pid << L" (" << getProcessName(pid) << L") has exited.\n";
73+
}
74+
}
75+
76+
for (DWORD pid : currentPids) {
77+
if (previousPids.find(pid) == previousPids.end()) {
78+
std::wcout << L"New process with PID " << pid << L" (" << getProcessName(pid) << L") has started.\n";
79+
}
80+
}
81+
}
82+
83+
void monitorSubProcesses(DWORD parentPid, bool& exitFlag) {
84+
std::set<DWORD> currentChildPids = { parentPid };
85+
while (!exitFlag) {
86+
std::vector<DWORD> childPids = getChildProcesses(parentPid);
87+
88+
std::set<DWORD> newChildPids(childPids.begin(), childPids.end());
89+
90+
logProcessStatus(currentChildPids, newChildPids);
91+
92+
currentChildPids = newChildPids;
93+
94+
// Wait for 1 second to update the list of subprocesses regularly
95+
std::this_thread::sleep_for(std::chrono::seconds(1));
96+
}
97+
}
98+
99+
void waitForAllProcesses(DWORD parentPid) {
100+
// Wait for the main process to finish
101+
waitForProcess(parentPid);
102+
103+
// Then wait for all child processes
104+
std::vector<DWORD> childPids = getChildProcesses(parentPid);
105+
for (DWORD childPid : childPids) {
106+
waitForProcess(childPid);
107+
}
108+
}
109+
110+
int wmain(int argc, wchar_t* argv[]) {
111+
if (argc < 2) {
112+
std::wcerr << L"Usage: " << argv[0] << L" <program>\n";
113+
return 1;
114+
}
115+
116+
wchar_t* program = argv[1];
117+
STARTUPINFO si = { sizeof(STARTUPINFO) };
118+
PROCESS_INFORMATION pi;
119+
120+
// Start the process
121+
if (!CreateProcess(
122+
NULL, // Application path
123+
program, // Command to run the program
124+
NULL, // Process security attributes
125+
NULL, // Thread security attributes
126+
FALSE, // No inheritance of handles
127+
CREATE_NEW_CONSOLE, // New console window
128+
NULL, // Environment (unchanged)
129+
NULL, // Current directory (unchanged)
130+
&si, // STARTUPINFO structure
131+
&pi // PROCESS_INFORMATION structure
132+
)) {
133+
std::wcerr << L"Failed to start process: " << GetLastError() << L"\n";
134+
return 1;
135+
}
136+
137+
std::wcout << L"Main process started: " << program << L"\n";
138+
139+
// Flag to exit the monitoring thread
140+
bool exitFlag = false;
141+
142+
// Start the process monitoring thread
143+
std::thread monitorThread(monitorSubProcesses, pi.dwProcessId, std::ref(exitFlag));
144+
145+
// Wait for the main process and all its child processes
146+
waitForAllProcesses(pi.dwProcessId);
147+
148+
std::wcout << L"Process and its children finished successfully.\n";
149+
150+
// Set the exit flag to stop the monitoring thread
151+
exitFlag = true;
152+
153+
// Wait for the monitoring thread to finish
154+
monitorThread.join();
155+
156+
// Close handles
157+
CloseHandle(pi.hProcess);
158+
CloseHandle(pi.hThread);
159+
160+
return 0;
161+
}

0 commit comments

Comments
 (0)