Last active
January 2, 2026 20:44
-
-
Save pedroinfo/563a72005d81ef6fd7ac2c2886a80079 to your computer and use it in GitHub Desktop.
SystemInfoHelper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Concurrent; | |
| using System.Collections.Generic; | |
| using System.Diagnostics; | |
| using System.Linq; | |
| using System.Management; | |
| public static class SystemInfoHelper | |
| { | |
| // Stores last CPU samples per PID (important if pool recycles) | |
| private static readonly ConcurrentDictionary<int, TimeSpan> _lastCpu = | |
| new ConcurrentDictionary<int, TimeSpan>(); | |
| private static readonly ConcurrentDictionary<int, DateTime> _lastSampleTime = | |
| new ConcurrentDictionary<int, DateTime>(); | |
| /// <summary> | |
| /// Returns the CPU usage percentage of an IIS App Pool worker process. | |
| /// Does NOT require PerformanceCounter or registry access. | |
| /// </summary> | |
| public static double GetCpuUsage(string appPoolName) | |
| { | |
| var process = GetProcessByAppPool(appPoolName); | |
| var pid = process.Id; | |
| var now = DateTime.UtcNow; | |
| var currentCpu = process.TotalProcessorTime; | |
| var lastCpu = _lastCpu.GetOrAdd(pid, TimeSpan.Zero); | |
| var lastTime = _lastSampleTime.GetOrAdd(pid, now); | |
| var cpuUsedMs = (currentCpu - lastCpu).TotalMilliseconds; | |
| var elapsedMs = (now - lastTime).TotalMilliseconds; | |
| _lastCpu[pid] = currentCpu; | |
| _lastSampleTime[pid] = now; | |
| if (elapsedMs <= 0) | |
| return 0; | |
| var cpuPercent = cpuUsedMs / (elapsedMs * Environment.ProcessorCount); | |
| cpuPercent = Math.Max(0, Math.Min(cpuPercent, 1)); | |
| return Math.Round(cpuPercent * 100, 2); | |
| } | |
| /// <summary> | |
| /// Returns the memory usage (Working Set) of an IIS App Pool worker process in MB. | |
| /// </summary> | |
| public static double GetMemoryUsageMB(string appPoolName) | |
| { | |
| var process = GetProcessByAppPool(appPoolName); | |
| var bytes = process.WorkingSet64; | |
| return Math.Round(bytes / 1024.0 / 1024.0, 2); | |
| } | |
| /// <summary> | |
| /// Returns readable uptime text for an IIS App Pool worker process. | |
| /// </summary> | |
| public static string GetReadableUptime(string appPoolName) | |
| { | |
| var process = GetProcessByAppPool(appPoolName); | |
| var uptime = DateTime.UtcNow - process.StartTime.ToUniversalTime(); | |
| return TimeSpanToReadableString(uptime); | |
| } | |
| /// <summary> | |
| /// Resolves the w3wp.exe process associated with an IIS App Pool. | |
| /// </summary> | |
| private static Process GetProcessByAppPool(string appPoolName) | |
| { | |
| using var searcher = new ManagementObjectSearcher( | |
| "SELECT ProcessId, CommandLine FROM Win32_Process WHERE Name='w3wp.exe'"); | |
| foreach (ManagementObject obj in searcher.Get()) | |
| { | |
| var cmd = obj["CommandLine"]?.ToString(); | |
| if (string.IsNullOrWhiteSpace(cmd)) | |
| continue; | |
| if (cmd.IndexOf("-ap", StringComparison.OrdinalIgnoreCase) >= 0 && | |
| cmd.IndexOf(appPoolName, StringComparison.OrdinalIgnoreCase) >= 0) | |
| { | |
| var pid = Convert.ToInt32(obj["ProcessId"]); | |
| return Process.GetProcessById(pid); | |
| } | |
| } | |
| throw new InvalidOperationException( | |
| $"App Pool '{appPoolName}' not found. Ensure the pool is running and received traffic."); | |
| } | |
| /// <summary> | |
| /// Converts a TimeSpan to a friendly human-readable string. | |
| /// </summary> | |
| private static string TimeSpanToReadableString(TimeSpan ts) | |
| { | |
| var parts = new List<string>(); | |
| if (ts.Days > 0) | |
| parts.Add($"{ts.Days} day{(ts.Days > 1 ? "s" : "")}"); | |
| if (ts.Hours > 0) | |
| parts.Add($"{ts.Hours} hour{(ts.Hours > 1 ? "s" : "")}"); | |
| if (ts.Minutes > 0) | |
| parts.Add($"{ts.Minutes} minute{(ts.Minutes > 1 ? "s" : "")}"); | |
| if (ts.Seconds > 0) | |
| parts.Add($"{ts.Seconds} second{(ts.Seconds > 1 ? "s" : "")}"); | |
| return parts.Count == 0 ? "0 seconds" : string.Join(", ", parts); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment