针对特定流程实例在C#中获取私有工作集内存的最佳方法

时间:2019-05-01 22:42:09

标签: c# windows winforms winapi

我正在构建一个小型控制台应用程序,该应用程序将强制关闭使用一定内存量的进程,并且在CPU已经使用大量电源的情况下,我正努力使其正常工作。

每当我使用PerformanceCounter来获取私有工作集内存时,我很容易陷入以下异常:

  

发生一个或多个错误

在我看来,如果我将PerformanceCounter“附加”到一个进程,我将无法再简单地 .Kill()。当然,即使要获取值,这也是一个较慢的过程。

使用任务管理器时,我可以清楚地看到进程的内存使用情况。如果进入“详细信息”选项卡,可以看到“内存”列实际上是“专用工作集”值。

有没有办法以更优化,更快的方式获得此价值?

这是我用来通过PerformanceCounter获取私有工作集的代码:

public static long GetPrivateWorkingSetMemoryOfProcess(Process process)
{
    long process_size = 0;
    String InstanceName = PerformanceCounterInstanceName(process);
    var counter = new PerformanceCounter("Process", "Working Set - Private", InstanceName, true);
    process_size = Convert.ToInt32(counter.NextValue()) / 1024;
    return process_size;
}

由于PerformanceCounter使用流程名称作为参数而不是ID,因此我使用此函数来获取正确的流程名称:

public static string PerformanceCounterInstanceName(this Process process)
{
    var matchesProcessId = new Func<string, bool>(instanceName =>
    {
        using (var pc = new PerformanceCounter("Process", "ID Process", instanceName, true))
        {
            if ((int)pc.RawValue == process.Id)
            {
                return true;
            }
        }
        return false;
    });

    string processName = Path.GetFileNameWithoutExtension(process.ProcessName);
    return new PerformanceCounterCategory("Process")
           .GetInstanceNames()
           .AsParallel()
           .FirstOrDefault(instanceName => instanceName.StartsWith(processName)
                                           && matchesProcessId(instanceName));
}

在这里我将用它杀死具有一定内存使用量的进程:

//get Process By ID
Process processToClose = Process.GetProcessById(Convert.ToInt32(processid));

long processesPrivateWorkingSetMemoryUsage = GetPrivateWorkingSetMemoryOfProcess(processToClose);
Console.WriteLine("Process '" + processid + "' uses " + processesPrivateWorkingSetMemoryUsage.ToString() + " memory.");
if (processesPrivateWorkingSetMemoryUsage <= 8000)
{
    processToClose.Kill()
}

1 个答案:

答案 0 :(得分:0)

代替使用API​​,一种解决方法是在C#中调用以下PowerShell命令。

(Get-Counter "\Process(notepad)\Working Set - Private").CounterSamples |
    Sort-Object InstanceName |
        Format-Table InstanceName, @{Label="PrivateWorkingSet"; Expression={$_.CookedValue / 1MB}} -AutoSize

在这里我以记事本为例。您可以为每个进程调用此命令以检查私有工作集。

终止过程:

Stop-Process -Name "notepad"

请参阅“ Executing PowerShell scripts from C#”“ Get-Counter - Example 14:Find processes on a computer with the largest working sets