22#pragma comment(lib, "ws2_32.lib")
23#pragma comment(lib, "iphlpapi.lib")
24#pragma comment(lib, "psapi.lib")
25#pragma comment(lib, "pdh.lib")
26#pragma comment(lib, "advapi32.lib")
32#include <sys/statvfs.h>
56 spStreamer->ProcessDiscovered += [fnOnProcess](
const void*,
const ProcessEventArgs& e) {
57 if (fnOnProcess) fnOnProcess(e.GetProcess());
60 spStreamer->Completed += [fnOnComplete](
const void*,
const EventArgs&) {
70 struct ProcessCpuSample {
71 uint64_t uProcessTime;
76 struct SystemMetricsWin32Helper {
80 MEMORYSTATUSEX memStatus;
81 memStatus.dwLength =
sizeof(MEMORYSTATUSEX);
82 if (::GlobalMemoryStatusEx(&memStatus)) {
85 info.
uMemoryUsedBytes =
static_cast<unsigned long long>(memStatus.ullTotalPhys - memStatus.ullAvailPhys);
90 static double CalculateCpuDelta(uint64_t uIdle, uint64_t uKernel, uint64_t uUser) {
92 static uint64_t s_uPrevIdle = 0, s_uPrevTotal = 0;
93 uint64_t uTotal = uKernel + uUser;
95 if (s_uPrevTotal > 0 && uTotal > s_uPrevTotal) {
96 uint64_t uTotalDiff = uTotal - s_uPrevTotal;
97 uint64_t uIdleDiff = uIdle - s_uPrevIdle;
98 dCpu =
static_cast<double>((uTotalDiff - uIdleDiff) * 100.0 / uTotalDiff);
99 }
else if (uTotal > 0) {
100 dCpu =
static_cast<double>((uTotal - uIdle) * 100.0 / uTotal);
102 s_uPrevIdle = uIdle; s_uPrevTotal = uTotal;
103 return (dCpu < 0.0) ? 0.0 : ((dCpu > 100.0) ? 100.0 : dCpu);
106 static double GetSystemCpu() {
108 FILETIME ftIdle, ftKernel, ftUser;
109 if (!::GetSystemTimes(&ftIdle, &ftKernel, &ftUser))
return 0.0;
110 uint64_t uIdle = (
static_cast<uint64_t
>(ftIdle.dwHighDateTime) << 32) | ftIdle.dwLowDateTime;
111 uint64_t uKernel = (
static_cast<uint64_t
>(ftKernel.dwHighDateTime) << 32) | ftKernel.dwLowDateTime;
112 uint64_t uUser = (
static_cast<uint64_t
>(ftUser.dwHighDateTime) << 32) | ftUser.dwLowDateTime;
113 return CalculateCpuDelta(uIdle, uKernel, uUser);
116 static void InitDiskQuery(HQUERY& hQuery, HCOUNTER& hRead, HCOUNTER& hWrite) {
118 static bool s_bPdhInitialized =
false;
119 if (!s_bPdhInitialized && ::PdhOpenQueryW(NULL, 0, &hQuery) == ERROR_SUCCESS) {
120 ::PdhAddEnglishCounterW(hQuery, L
"\\PhysicalDisk(_Total)\\Disk Read Bytes/sec", 0, &hRead);
121 ::PdhAddEnglishCounterW(hQuery, L
"\\PhysicalDisk(_Total)\\Disk Write Bytes/sec", 0, &hWrite);
122 ::PdhCollectQueryData(hQuery);
123 s_bPdhInitialized =
true;
130 static HQUERY s_hQuery = NULL;
static HCOUNTER s_hRead = NULL, s_hWrite = NULL;
131 InitDiskQuery(s_hQuery, s_hRead, s_hWrite);
132 if (s_hQuery && ::PdhCollectQueryData(s_hQuery) == ERROR_SUCCESS) {
133 PDH_FMT_COUNTERVALUE fmtRead, fmtWrite;
134 if (::PdhGetFormattedCounterValue(s_hRead, PDH_FMT_LARGE, NULL, &fmtRead) == ERROR_SUCCESS) info.
lDiskReadBytes =
static_cast<long long>(fmtRead.largeValue);
135 if (::PdhGetFormattedCounterValue(s_hWrite, PDH_FMT_LARGE, NULL, &fmtWrite) == ERROR_SUCCESS) info.
lDiskWriteBytes =
static_cast<long long>(fmtWrite.largeValue);
140 static double CalculateNetRate(uint64_t totalOctets) {
142 static uint64_t s_uPrevOctets = 0;
static DWORD s_dwPrevTick = 0;
143 DWORD dwNow = ::GetTickCount();
double dMbps = 0.0;
144 if (s_dwPrevTick > 0 && dwNow > s_dwPrevTick && totalOctets >= s_uPrevOctets) {
145 double dElapsedSec = (dwNow - s_dwPrevTick) / 1000.0;
146 dMbps = ((totalOctets - s_uPrevOctets) / dElapsedSec * 8.0) / 1000000.0;
148 s_uPrevOctets = totalOctets; s_dwPrevTick = dwNow;
152 static double GetSystemNetwork() {
155 if (::GetIfTable(NULL, &dwSize, FALSE) != ERROR_INSUFFICIENT_BUFFER)
return 0.0;
156 std::vector<uint8_t> buf(dwSize, 0);
157 MIB_IFTABLE* pTable =
reinterpret_cast<MIB_IFTABLE*
>(buf.data());
158 if (::GetIfTable(pTable, &dwSize, FALSE) != NO_ERROR)
return 0.0;
159 uint64_t totalOctets = 0;
160 for (DWORD i = 0; i < pTable->dwNumEntries; ++i) {
161 if (pTable->table[i].dwType != IF_TYPE_SOFTWARE_LOOPBACK && pTable->table[i].dwOperStatus == IF_OPER_STATUS_OPERATIONAL)
162 totalOctets += pTable->table[i].dwInOctets + pTable->table[i].dwOutOctets;
164 return CalculateNetRate(totalOctets);
167 static void* OpenProcByName(
const String& sProcessName,
unsigned long dwAccess,
int& iOutPid) {
171 if (arrMatches.GetLength() == 0)
return NULL;
172 iOutPid = arrMatches[0]->GetId();
173 return ::OpenProcess(dwAccess, FALSE,
static_cast<DWORD
>(iOutPid));
176 static String ReadPebCommandLine(HANDLE hProc, PVOID pebBase) {
178 PEB peb; SIZE_T bytesRead = 0;
179 if (!::ReadProcessMemory(hProc, pebBase, &peb,
sizeof(peb), &bytesRead))
return String(
"");
180 RTL_USER_PROCESS_PARAMETERS upp;
181 if (!::ReadProcessMemory(hProc, peb.ProcessParameters, &upp,
sizeof(upp), &bytesRead) || !upp.CommandLine.Buffer || upp.CommandLine.Length == 0)
return String(
"");
182 std::vector<wchar_t> wCmd(upp.CommandLine.Length /
sizeof(
wchar_t) + 1, 0);
183 if (::ReadProcessMemory(hProc, upp.CommandLine.Buffer, wCmd.data(), upp.CommandLine.Length, &bytesRead))
return String(wCmd.data());
187 static String ReadProcCmdLine(
void* hProc) {
189 typedef NTSTATUS(NTAPI* pfnNtQuery)(HANDLE, ULONG, PVOID, ULONG, PULONG);
190 HMODULE hNtDll = ::GetModuleHandleW(L
"ntdll.dll");
191 pfnNtQuery fnNtQuery = hNtDll ? (pfnNtQuery)::GetProcAddress(hNtDll,
"NtQueryInformationProcess") : NULL;
192 if (!fnNtQuery || !hProc)
return String(
"");
193 PROCESS_BASIC_INFORMATION pbi; DWORD dwLen = 0;
194 if (fnNtQuery(
static_cast<HANDLE
>(hProc), 0, &pbi,
sizeof(pbi), &dwLen) == 0 && pbi.PebBaseAddress) {
195 return ReadPebCommandLine(
static_cast<HANDLE
>(hProc), pbi.PebBaseAddress);
200 static MemoryInfo ReadProcMemory(
void* hProc) {
204 PROCESS_MEMORY_COUNTERS_EX pmc;
205 if (::GetProcessMemoryInfo(
static_cast<HANDLE
>(hProc),
reinterpret_cast<PROCESS_MEMORY_COUNTERS*
>(&pmc),
sizeof(pmc))) {
207 info.
lPrivateBytes =
static_cast<long long>(pmc.PrivateUsage);
213 static void QueryPdhIoCounters(
const std::wstring& wProcName,
DiskInfo& info) {
215 std::wstring rPath = L
"\\Process(" + wProcName + L
")\\IO Read Bytes/sec";
216 std::wstring wPath = L
"\\Process(" + wProcName + L
")\\IO Write Bytes/sec";
217 HQUERY hQuery = NULL; HCOUNTER hRead = NULL, hWrite = NULL;
218 if (::PdhOpenQueryW(NULL, 0, &hQuery) != ERROR_SUCCESS)
return;
219 bool rOk = (::PdhAddEnglishCounterW(hQuery, rPath.c_str(), 0, &hRead) == ERROR_SUCCESS);
220 bool wOk = (::PdhAddEnglishCounterW(hQuery, wPath.c_str(), 0, &hWrite) == ERROR_SUCCESS);
221 if (::PdhCollectQueryData(hQuery) == ERROR_SUCCESS) {
222 PDH_FMT_COUNTERVALUE fmtR, fmtW;
223 if (rOk && ::PdhGetFormattedCounterValue(hRead, PDH_FMT_LARGE, NULL, &fmtR) == ERROR_SUCCESS) info.
lDiskReadBytes =
static_cast<long long>(fmtR.largeValue);
224 if (wOk && ::PdhGetFormattedCounterValue(hWrite, PDH_FMT_LARGE, NULL, &fmtW) == ERROR_SUCCESS) info.
lDiskWriteBytes =
static_cast<long long>(fmtW.largeValue);
226 ::PdhCloseQuery(hQuery);
229 static DiskInfo ReadProcDisk(
void* hProc,
const String& sProcessName) {
233 std::wstring wProc(sStd.begin(), sStd.end());
234 size_t pos = wProc.rfind(L
'.');
if (pos != std::wstring::npos) wProc = wProc.substr(0, pos);
235 QueryPdhIoCounters(wProc, info);
238 if (::GetProcessIoCounters(
static_cast<HANDLE
>(hProc), &io)) {
250 std::wstring wProc(sStd.begin(), sStd.end());
251 size_t pos = wProc.rfind(L
'.');
if (pos != std::wstring::npos) wProc = wProc.substr(0, pos);
253 QueryPdhIoCounters(wProc, di);
261 if (iPid <= 0)
return;
263 if (::GetExtendedUdpTable(NULL, &dwSize, FALSE, AF_INET, UDP_TABLE_OWNER_PID, 0) != ERROR_INSUFFICIENT_BUFFER)
return;
264 std::vector<uint8_t> buf(dwSize, 0);
265 MIB_UDPTABLE_OWNER_PID* pTable =
reinterpret_cast<MIB_UDPTABLE_OWNER_PID*
>(buf.data());
266 if (::GetExtendedUdpTable(pTable, &dwSize, FALSE, AF_INET, UDP_TABLE_OWNER_PID, 0) != NO_ERROR)
return;
267 for (DWORD i = 0; i < pTable->dwNumEntries; ++i) {
268 if (pTable->table[i].dwOwningPid ==
static_cast<DWORD
>(iPid)) {
269 int p = ntohs(
static_cast<u_short
>(pTable->table[i].dwLocalPort));
278 if (iPid <= 0)
return lst;
280 if (::GetExtendedTcpTable(NULL, &dwSize, FALSE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0) == ERROR_INSUFFICIENT_BUFFER) {
281 std::vector<uint8_t> buf(dwSize, 0);
282 MIB_TCPTABLE_OWNER_PID* pTable =
reinterpret_cast<MIB_TCPTABLE_OWNER_PID*
>(buf.data());
283 if (::GetExtendedTcpTable(pTable, &dwSize, FALSE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0) == NO_ERROR) {
284 for (DWORD i = 0; i < pTable->dwNumEntries; ++i) {
285 if (pTable->table[i].dwOwningPid ==
static_cast<DWORD
>(iPid) && pTable->table[i].dwState == MIB_TCP_STATE_LISTEN) {
286 int p = ntohs(
static_cast<u_short
>(pTable->table[i].dwLocalPort));
292 ReadUdpPorts(iPid, lst);
298 in_addr lAddr, rAddr;
299 lAddr.S_un.S_addr = row.dwLocalAddr; rAddr.S_un.S_addr = row.dwRemoteAddr;
300 char szL[INET_ADDRSTRLEN] = { 0 }, szR[INET_ADDRSTRLEN] = { 0 };
301 ::inet_ntop(AF_INET, &lAddr, szL,
sizeof(szL));
302 ::inet_ntop(AF_INET, &rAddr, szR,
sizeof(szR));
305 conn.
sState = (row.dwState == MIB_TCP_STATE_LISTEN) ?
"LISTEN" : ((row.dwState == MIB_TCP_STATE_ESTAB) ?
"ESTABLISHED" :
"OTHER");
310 if (iPid <= 0)
return;
312 if (::GetExtendedUdpTable(NULL, &dwSize, FALSE, AF_INET, UDP_TABLE_OWNER_PID, 0) != ERROR_INSUFFICIENT_BUFFER)
return;
313 std::vector<uint8_t> buf(dwSize, 0);
314 MIB_UDPTABLE_OWNER_PID* pTable =
reinterpret_cast<MIB_UDPTABLE_OWNER_PID*
>(buf.data());
315 if (::GetExtendedUdpTable(pTable, &dwSize, FALSE, AF_INET, UDP_TABLE_OWNER_PID, 0) != NO_ERROR)
return;
316 for (DWORD i = 0; i < pTable->dwNumEntries; ++i) {
317 if (pTable->table[i].dwOwningPid ==
static_cast<DWORD
>(iPid)) {
318 int p = ntohs(
static_cast<u_short
>(pTable->table[i].dwLocalPort));
321 in_addr lAddr; lAddr.S_un.S_addr = pTable->table[i].dwLocalAddr;
322 char szL[INET_ADDRSTRLEN] = { 0 };
323 ::inet_ntop(AF_INET, &lAddr, szL,
sizeof(szL));
333 if (iPid <= 0)
return info;
335 if (::GetExtendedTcpTable(NULL, &dwSize, FALSE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0) == ERROR_INSUFFICIENT_BUFFER) {
336 std::vector<uint8_t> buf(dwSize, 0);
337 MIB_TCPTABLE_OWNER_PID* pTable =
reinterpret_cast<MIB_TCPTABLE_OWNER_PID*
>(buf.data());
338 if (::GetExtendedTcpTable(pTable, &dwSize, FALSE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0) == NO_ERROR) {
339 for (DWORD i = 0; i < pTable->dwNumEntries; ++i) {
340 if (pTable->table[i].dwOwningPid ==
static_cast<DWORD
>(iPid)) {
342 ExtractTcpConnection(pTable->table[i], conn);
350 ReadUdpConnections(iPid, info);
354 static void CalculateProcessCpu(HANDLE hProc,
int iPid,
double& dCpu) {
356 FILETIME ftCreate, ftExit, ftKernel, ftUser, ftSysIdle, ftSysKernel, ftSysUser, ftNow;
357 if (!::GetProcessTimes(hProc, &ftCreate, &ftExit, &ftKernel, &ftUser) || !::GetSystemTimes(&ftSysIdle, &ftSysKernel, &ftSysUser))
return;
358 uint64_t uProc = ((
static_cast<uint64_t
>(ftKernel.dwHighDateTime) << 32) | ftKernel.dwLowDateTime) + ((
static_cast<uint64_t
>(ftUser.dwHighDateTime) << 32) | ftUser.dwLowDateTime);
359 uint64_t uSys = ((
static_cast<uint64_t
>(ftSysKernel.dwHighDateTime) << 32) | ftSysKernel.dwLowDateTime) + ((
static_cast<uint64_t
>(ftSysUser.dwHighDateTime) << 32) | ftSysUser.dwLowDateTime);
361 if (it !=
s_mapProcessCpuSamples.end() && uSys > it->second.uSystemTime && uProc >= it->second.uProcessTime) {
362 double c = (
static_cast<double>(uProc - it->second.uProcessTime) * 100.0 /
static_cast<double>(uSys - it->second.uSystemTime));
363 dCpu = (c > 100.0) ? 100.0 : ((c < 0.0) ? 0.0 : c);
365 ::GetSystemTimeAsFileTime(&ftNow); SYSTEM_INFO si; ::GetSystemInfo(&si);
366 uint64_t uNow = (
static_cast<uint64_t
>(ftNow.dwHighDateTime) << 32) | ftNow.dwLowDateTime; uint64_t uCreate = (
static_cast<uint64_t
>(ftCreate.dwHighDateTime) << 32) | ftCreate.dwLowDateTime;
367 if (uNow > uCreate && uProc > 0) {
double c = (
static_cast<double>(uProc) * 100.0) / (
static_cast<double>(uNow - uCreate) *
static_cast<double>(si.dwNumberOfProcessors > 0 ? si.dwNumberOfProcessors : 1)); dCpu = (c > 100.0) ? 100.0 : ((c < 0.0) ? 0.0 : c); }
372 static void PopulateProcNetwork(
int iPid,
ProcessInfo& proc) {
374 auto netInfo = ReadProcNetInfo(iPid);
380 static String GetServiceStartType(SC_HANDLE hSCM, LPCWSTR lpServiceName) {
382 SC_HANDLE hService = ::OpenServiceW(hSCM, lpServiceName, SERVICE_QUERY_CONFIG);
383 if (!hService)
return "Manual";
384 BYTE buffer[1024]; DWORD dwNeeded = 0;
385 QUERY_SERVICE_CONFIGW* pConfig =
reinterpret_cast<QUERY_SERVICE_CONFIGW*
>(buffer);
387 if (::QueryServiceConfigW(hService, pConfig,
sizeof(buffer), &dwNeeded)) {
388 switch (pConfig->dwStartType) {
389 case SERVICE_AUTO_START: sType =
"Automatic";
break;
390 case SERVICE_DEMAND_START: sType =
"Manual";
break;
391 case SERVICE_DISABLED: sType =
"Disabled";
break;
392 case SERVICE_BOOT_START: sType =
"Boot";
break;
393 case SERVICE_SYSTEM_START: sType =
"System";
break;
394 default: sType =
"Manual";
break;
397 ::CloseServiceHandle(hService);
401 static void ParseServiceStatus(ENUM_SERVICE_STATUS_PROCESSW& svc, SC_HANDLE hSCM,
ServiceInfo& info) {
404 info.
iProcessId =
static_cast<int>(svc.ServiceStatusProcess.dwProcessId);
405 switch (svc.ServiceStatusProcess.dwCurrentState) {
406 case SERVICE_RUNNING: info.
sStatus =
"Running";
break;
407 case SERVICE_STOPPED: info.
sStatus =
"Stopped";
break;
408 case SERVICE_PAUSED: info.
sStatus =
"Paused";
break;
409 case SERVICE_START_PENDING: info.
sStatus =
"StartPending";
break;
410 case SERVICE_STOP_PENDING: info.
sStatus =
"StopPending";
break;
411 default: info.
sStatus =
"Unknown";
break;
413 info.
sStartType = GetServiceStartType(hSCM, svc.lpServiceName);
422 void* SystemMetrics::OpenProcessByName(
const String& sProcessName,
unsigned long dwDesiredAccess,
int& iOutProcessId) {
423 return SystemMetricsWin32Helper::OpenProcByName(sProcessName, dwDesiredAccess, iOutProcessId);
426 String SystemMetrics::ReadProcessCommandLineHandle(
void* hProc) {
427 return SystemMetricsWin32Helper::ReadProcCmdLine(hProc);
433 HANDLE hProc =
static_cast<HANDLE
>(OpenProcessByName(sProcessName, PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, iPid));
434 if (!hProc)
return String(
"");
435 String sCmd = ReadProcessCommandLineHandle(hProc);
437 WCHAR szPath[MAX_PATH] = { 0 }; DWORD dwLen = MAX_PATH;
438 if (::QueryFullProcessImageNameW(hProc, 0, szPath, &dwLen)) sCmd =
String(szPath);
440 ::CloseHandle(hProc);
444 MemoryInfo SystemMetrics::ReadProcessMemoryHandle(
void* hProc) {
return SystemMetricsWin32Helper::ReadProcMemory(hProc); }
447 int iPid = -1; HANDLE hProc =
static_cast<HANDLE
>(OpenProcessByName(sProcessName, PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, iPid));
449 MemoryInfo mem = ReadProcessMemoryHandle(hProc);
450 ::CloseHandle(hProc);
454 DiskInfo SystemMetrics::ReadProcessDiskHandle(
void* hProc,
const String& sProcessName) {
return SystemMetricsWin32Helper::ReadProcDisk(hProc, sProcessName); }
457 int iPid = -1; HANDLE hProc =
static_cast<HANDLE
>(OpenProcessByName(sProcessName, PROCESS_QUERY_LIMITED_INFORMATION, iPid));
458 DiskInfo di = ReadProcessDiskHandle(hProc, sProcessName);
459 if (hProc) ::CloseHandle(hProc);
463 NetworkUsageInfo SystemMetrics::ReadProcessNetworkHandle(
void* hProc,
const String& sProcessName) {
return SystemMetricsWin32Helper::ReadProcNetwork(hProc, sProcessName); }
466 int iPid = -1; HANDLE hProc =
static_cast<HANDLE
>(OpenProcessByName(sProcessName, PROCESS_QUERY_LIMITED_INFORMATION, iPid));
468 if (hProc) ::CloseHandle(hProc);
472 Collections::Generic::List<int> SystemMetrics::ReadProcessNetworkPortInternal(
int iProcessId) {
return SystemMetricsWin32Helper::ReadProcPorts(iProcessId); }
474 int iPid = -1; HANDLE hProc =
static_cast<HANDLE
>(OpenProcessByName(sProcessName, PROCESS_QUERY_LIMITED_INFORMATION, iPid));
475 if (hProc) ::CloseHandle(hProc);
476 return ReadProcessNetworkPortInternal(iPid);
479 return ReadProcessNetworkPortInternal(iProcessId);
482 ProcessNetworkConnectionInfo SystemMetrics::ReadProcessNetworkInfoInternal(
int iProcessId) {
return SystemMetricsWin32Helper::ReadProcNetInfo(iProcessId); }
484 int iPid = -1; HANDLE hProc =
static_cast<HANDLE
>(OpenProcessByName(sProcessName, PROCESS_QUERY_LIMITED_INFORMATION, iPid));
485 if (hProc) ::CloseHandle(hProc);
486 return ReadProcessNetworkInfoInternal(iPid);
489 return ReadProcessNetworkInfoInternal(iProcessId);
497 HANDLE hProc = ::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, FALSE, proc.
iProcessId);
500 WCHAR szPath[MAX_PATH] = { 0 }; DWORD dwLen = MAX_PATH;
501 if (::QueryFullProcessImageNameW(hProc, 0, szPath, &dwLen)) proc.
sPath =
String(szPath);
503 proc.
sCommandLine = SystemMetricsWin32Helper::ReadProcCmdLine(hProc);
505 proc.
memory = SystemMetricsWin32Helper::ReadProcMemory(hProc);
506 proc.
disk = SystemMetricsWin32Helper::ReadProcDisk(hProc, proc.
sName);
507 proc.
network = SystemMetricsWin32Helper::ReadProcNetwork(hProc, proc.
sName);
509 ::CloseHandle(hProc);
513 if (bIncludeNetwork) SystemMetricsWin32Helper::PopulateProcNetwork(proc.
iProcessId, proc);
519 SC_HANDLE hSCM = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
520 if (!hSCM)
return lst;
521 DWORD dwNeeded = 0, dwReturned = 0, dwResume = 0;
522 ::EnumServicesStatusExW(hSCM, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &dwNeeded, &dwReturned, &dwResume, NULL);
524 std::vector<uint8_t> buf(dwNeeded, 0);
525 ENUM_SERVICE_STATUS_PROCESSW* pSvcs =
reinterpret_cast<ENUM_SERVICE_STATUS_PROCESSW*
>(buf.data());
526 if (::EnumServicesStatusExW(hSCM, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, buf.data(), dwNeeded, &dwNeeded, &dwReturned, &dwResume, NULL)) {
527 for (DWORD i = 0; i < dwReturned; ++i) {
528 ServiceInfo svc; SystemMetricsWin32Helper::ParseServiceStatus(pSvcs[i], hSCM, svc);
533 ::CloseServiceHandle(hSCM);
Defines the exception thrown when an invalid argument is provided to a method.
Provides access to local and remote processes and enables you to start and stop local system processe...
Utility routines for high-performance UTF-8, UTF-16, and wide-character string conversions.
Serves as the base class for system exceptions across the library.
Encapsulates a method that has parameters and does not return a value.
ArgumentException(const String &sMessage)
Initializes a new instance of the ArgumentException class with a specified error message.
Represents a strongly typed list of objects accessible by index.
bool Contains(const T &item) const
Determines whether an element is in the List.
void Add(const T &item)
Adds an object to the end of the List.
Event arguments containing a single process snapshot.
static Array< SmartPointer< Process > > GetProcessesByName(const String &sProcessName)
Creates an array of new Process components and associates them with all processes sharing the specifi...
static String GetProcessCommandLine(const String &sProcessName)
Queries the full command line used to launch a process by name.
static void EnrichProcessInfo(ProcessInfo &proc, bool bIncludeNetwork=true)
Enriches an existing ProcessInfo instance with CPU, memory, disk, and network telemetry.
static Collections::Generic::List< int > GetProcessNetworkPort(const String &sProcessName)
Retrieves open listening ports bound by a process by name.
static SmartPointer< ProcessStreamer > CreateProcessStreamer(const ProcessStreamOptions &options=ProcessStreamOptions())
Creates a background process streaming engine configured with options.
virtual ~SystemMetrics()
Virtual destructor.
static DiskInfo GetProcessDiskUsage(const String &sProcessName)
Queries disk transfer throughput for a process by name.
static MemoryInfo GetProcessMemoryUsage(const String &sProcessName)
Queries memory allocation details for a process by name.
static Collections::Generic::List< ServiceInfo > GetAllServices()
Enumerates all registered system background services and their current execution status.
SystemMetrics()
Initializes a new instance of SystemMetrics.
static MemoryInfo GetSystemMemoryUsage()
Retrieves total and consumed physical memory metrics for the entire machine.
static double GetSystemCpuUsage()
Computes total system CPU usage percentage across all processors.
static double GetSystemNetworkUsage()
Computes total network traffic throughput across all operational interfaces in Megabits per second.
static NetworkUsageInfo GetProcessNetworkUsage(const String &sProcessName)
Queries network transfer metrics for a process by name.
static ProcessNetworkConnectionInfo GetProcessNetworkInfo(const String &sProcessName)
Queries detailed socket connections for a process by name.
static void EnumerateProcessesAsync(const Action< const ProcessInfo & > &fnOnProcess, const Action<> &fnOnComplete=nullptr)
Asynchronously discovers processes on the host using fast discovery mode.
static DiskInfo GetSystemDiskUsage()
Retrieves total disk read and write transfer rates for the system.
Represents the base class for classes that contain event data, and provides a value to use for events...
A unified smart pointer that supports both unique and shared ownership semantics.
static SmartPointer< T > NewShared()
Creates a Shared SmartPointer, default constructing T.
Represents text as a sequence of UTF-8 code units with culture-invariant operations.
String()
Initializes a new instance of the String class to an empty string.
const char * GetRawString() const
@ FastDiscoveryOnly
Minimal discovery retrieving PID, name, and paths without deep inspection.
static std::map< int, ProcessCpuSample > s_mapProcessCpuSamples
Rate or aggregate count of disk read and write operations.
long long lDiskWriteBytes
Disk write throughput in bytes per second or total transfer count.
long long lDiskReadBytes
Disk read throughput in bytes per second or total transfer count.
Snapshot of physical and virtual memory utilization for the system or a specific process.
MemoryInfo()
Default constructor initializing default counters.
long long lPhysicalMemoryBytes
Working set size (physical RAM resident) for the target process.
unsigned long long uMemoryTotalBytes
Total physical RAM installed on the host in bytes.
double dMemoryUsagePercent
Percentage of total physical memory currently in use (0.0 - 100.0).
long long lPrivateBytes
Private bytes allocated by the target process (-1 if unavailable).
unsigned long long uMemoryUsedBytes
Currently consumed physical RAM across all processes.
Telemetry describing an active TCP or UDP socket endpoint.
int iRemotePort
Remote peer port.
String sState
Socket connection state (e.g. "ESTABLISHED", "LISTEN", "TIME_WAIT").
String sLocalAddress
Local IPv4 or IPv6 IP address.
String sRemoteAddress
Remote peer IP address.
int iLocalPort
Local listening or bound port.
Network throughput counters for bytes transmitted and received.
long long lNetworkReadBytes
Incoming network throughput in bytes or octets.
long long lNetworkWriteBytes
Outgoing network throughput in bytes or octets.
Comprehensive telemetry snapshot for an operating system process.
double dCpuUsagePercent
Process CPU consumption percentage (0.0 - 100.0).
String sName
Process executable name without path.
Collections::Generic::List< int > lstOpenPorts
Open listening ports.
int iProcessId
Operating system process identifier (PID).
NetworkUsageInfo network
Network traffic metrics.
String sCommandLine
Full command-line arguments used to spawn the process.
DiskInfo disk
Disk I/O telemetry.
bool bHasEstablishedConnection
True if any connection is established.
String sPath
Full filesystem path to the executable image.
MemoryInfo memory
Memory allocation statistics.
Collections::Generic::List< NetworkConnectionInfo > lstConnections
Active socket connections.
Collection of open ports and active connections attributed to a specific process.
Collections::Generic::List< NetworkConnectionInfo > lstConnections
Detailed active socket connections.
bool bHasEstablishedInboundConnection
True if process possesses at least one established connection.
Collections::Generic::List< int > lstOpenPorts
List of TCP/UDP ports bound or in LISTEN state.
Configuration options controlling the execution of a ProcessStreamer.
ProcessMetricsDetail eDetailLevel
Depth of telemetry gathered for each process.
Telemetry snapshot for a system background service or daemon.
int iProcessId
Process ID hosting the service (0 if stopped).
String sDisplayName
Human-readable friendly display name.
String sStartType
Startup behavior (e.g. "Automatic", "Manual", "Disabled").
String sStatus
Current service state (e.g. "Running", "Stopped", "Paused").
String sServiceName
Internal service key identifier.