如何获取已退出Windows进程的最大内存使用量?
获取已退出Windows进程的最大内存使用量
好问题!我之前处理类似需求的时候试过几个可行的方案,这里分享给你:
方案一:进程运行时实时监控并记录最大值
这是最直接也最可靠的方式——既然进程退出后内存属性不可用,那我们就在它运行的时候定期采样,把最大内存值记录下来。你可以用后台线程或者定时器来做这件事,平衡采样精度和性能。
示例代码:
var startInfo = new ProcessStartInfo("your-app.exe") { RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using var process = Process.Start(startInfo); if (process == null) { Console.WriteLine("进程启动失败"); return; } long maxMemoryUsage = 0; var monitorThread = new Thread(() => { while (!process.HasExited) { try { // 这里可以根据需求换PrivateMemorySize64、VirtualMemorySize64等属性 var currentMemory = process.WorkingSet64; if (currentMemory > maxMemoryUsage) { maxMemoryUsage = currentMemory; } Thread.Sleep(100); // 调整采样间隔,比如50ms会更精准但占用略高 } catch (InvalidOperationException) { // 进程可能刚退出,直接跳出循环 break; } } }); monitorThread.Start(); // 等待进程完成 process.WaitForExit(); // 确保监控线程也完成 monitorThread.Join(); // 输出结果 Console.WriteLine($"进程退出代码:{process.ExitCode}"); Console.WriteLine($"最大内存使用量:{maxMemoryUsage / (1024 * 1024)} MB");
方案二:使用Windows性能计数器
Windows性能计数器可以追踪进程的各类内存指标,你可以在进程运行时关联对应的计数器,实时记录最大值。它提供的指标比Process类的属性更丰富,比如私有字节、虚拟内存大小等。
示例代码:
var startInfo = new ProcessStartInfo("your-app.exe") { UseShellExecute = false }; using var process = Process.Start(startInfo); if (process == null) return; // 初始化性能计数器,这里选"Private Bytes"作为监控指标 using var memoryCounter = new PerformanceCounter( "Process", "Private Bytes", process.ProcessName, true); long maxPrivateBytes = 0; while (!process.HasExited) { var currentBytes = (long)memoryCounter.NextValue(); if (currentBytes > maxPrivateBytes) { maxPrivateBytes = currentBytes; } Thread.Sleep(100); } process.WaitForExit(); Console.WriteLine($"最大私有字节数:{maxPrivateBytes / (1024 * 1024)} MB"); Console.WriteLine($"退出代码:{process.ExitCode}");
方案三:通过WMI查询峰值内存
WMI的Win32_Process类提供了PeakWorkingSetSize属性,直接对应进程的峰值内存使用量。不过要注意,进程退出后WMI实例可能会被系统快速回收,所以需要在进程刚退出时立即查询。
示例代码:
using System.Management; var startInfo = new ProcessStartInfo("your-app.exe"); using var process = Process.Start(startInfo); if (process == null) return; process.WaitForExit(); // 进程刚退出时立即查询WMI var query = new ObjectQuery($"SELECT PeakWorkingSetSize FROM Win32_Process WHERE ProcessId = {process.Id}"); using var searcher = new ManagementObjectSearcher(query); var results = searcher.Get(); foreach (var obj in results) { var peakMemory = (ulong)obj["PeakWorkingSetSize"]; Console.WriteLine($"峰值工作集大小:{peakMemory / (1024 * 1024)} MB"); } Console.WriteLine($"退出代码:{process.ExitCode}");
方案对比
- 方案一:简单易实现,不需要额外权限,精度可控,是最稳妥的选择。唯一需要注意的是采样间隔的调整,避免遗漏短时间内的内存峰值。
- 方案二:指标更丰富,但需要熟悉性能计数器的命名规则,且进程退出后计数器实例会被清理,无法事后查询。
- 方案三:可以直接获取系统记录的峰值,不需要自己采样,但依赖WMI服务,且进程退出后可能查不到数据,稳定性不如前两种。
总的来说,方案一是我最推荐的方式,毕竟进程退出后系统不会主动保留内存使用的历史数据,实时记录是最可靠的办法。
内容的提问来源于stack exchange,提问作者Daniel Williams
相关产品推荐
相关产品推荐

