C# 从特定进程(性能计数器)获取 CPU 和 RAM

C# Get CPU and RAM from specific process (performance counters)

我想检索当时前台进程(或特定进程)的 cpu 和 ram 使用情况。
检索窗口的标题不是问题,并且该部分有效。但即使活动窗口以 70% 或更多的 CPU 运行,CPU 显示仍保持在 0%。

(int)pCPU.NextValue(); // <<<< 一直返回 0...

注意:我想用性能计数器来做。我不想使用 Process 变量来执行此操作,因为这可能会引发 \\'insufficient privilege errors\\'。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    [DllImport("user32.dll")]
    static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll")]
    static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

    [DllImport("user32.dll")]
    public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint ProcessId);

    public void GetActiveCPUAndRam(out string windowTitle, out int CPUUsagePerc, out int RAMUsage)
    {
        IntPtr hwnd = GetForegroundWindow();
        uint pid;
        GetWindowThreadProcessId(hwnd, out pid);

        Process activeProc = Process.GetProcessById((int) pid);

        #region Window Title

        const int nChars = 256;
        StringBuilder Buff = new StringBuilder(nChars);
        if (GetWindowText(hwnd, Buff, nChars) > 0)
            windowTitle = Buff.ToString();
        else
        {
            windowTitle ="";
            CPUUsagePerc = 0;
            RAMUsage = 0;
            return;
        }

        #endregion

        #region RAM/CPU
        PerformanceCounter pCPU = new PerformanceCounter("Process","% Processor Time", activeProc.ProcessName, true);
        pCPU.NextValue();
        CPUUsagePerc = (int)pCPU.NextValue(); // <<<<< problem here.

        RAMUsage = 0; // TODO:

        #endregion
    }

编辑:
我尝试了新的解决方案:
但是当我运行一个 cpu 压力测试程序将 cpu 使用率推到 100% (single core) 时。然后下面的解决方案显示该进程的cpu使用率就像总cpu的300-400%......显然还是有问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
        private PerformanceCounter pCPU = null;
        private IntPtr PreviousProcHwnd = IntPtr.Zero;
        private CounterSample PreviousCPUCounterSample = CounterSample.Empty;

        public void GetActiveCPUAndRam(out string windowTitle, out int CPUUsagePerc, out int RAMUsage)
{
        ...
        #region RAM/CPU

        if (PreviousProcHwnd != hwnd)
        {
            PreviousProcHwnd = hwnd;
            pCPU = new PerformanceCounter("Process","% Processor Time", activeProc.ProcessName,
                                                             true);
            PreviousCPUCounterSample = CounterSample.Empty;
        }

        CounterSample sample1 = pCPU.NextSample();
        CPUUsagePerc = (int)CounterSample.Calculate(PreviousCPUCounterSample, sample1);
        PreviousCPUCounterSample = sample1;
        RAMUsage = 0; // TODO:

        #endregion
}


不要直接使用数值,使用计算出的样本,

1
2
CounterSample sample1 = pCPU.NextSample();
float value = CounterSample.Calculate(sample1);

如果你的计数器是一个\\'rate\\'类型的样本,那么你需要得到两个样本,

1
2
3
4
CounterSample sample1 = counter.NextSample();
Thread.Sleep(1000); // wait some time
CounterSample sample2 = counter.NextSample();
float value = CounterSample.Calculate(sample1, sample2);