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

发布于 2024-12-31 21:12:56 字数 2741 浏览 2 评论 0原文

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

(int)pCPU.NextValue(); // <<<<<不断返回 0...

注意:我想用性能计数器来做到这一点。我不想使用 Process 变量来执行此操作,因为这可能会引发“权限不足错误”。

    [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
    }



EDIT: I tried the new solution: But when I run a cpu stress test program that pushes the cpu usage to 100% (single core) . Then the solution below shows that the cpu usage of that process is like 300-400% of the total cpu... Obviously something is still wrong.


        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
}

I would like to retrieve the cpu and ram usage at that point for the foreground process (or a specific one).
Retrieving the window's title is not a problem and that part works. But the cpu display stays at 0% even when the active window is running at 70% cpu or more.

(int)pCPU.NextValue(); // <<<< keeps returning 0...

Note: I want to do it with a performance counter. I don't want to do it using the Process variable because that one might raise 'insufficient privilege errors'.

    [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
    }


EDIT:
I tried the new solution:
But when I run a cpu stress test program that pushes the cpu usage to 100% (single core) . Then the solution below shows that the cpu usage of that process is like 300-400% of the total cpu... Obviously something is still wrong.


        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
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

站稳脚跟 2025-01-07 21:12:56

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

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

如果您的计数器是“速率”类型样本,那么您将需要获取两个样本,

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

Do not use the value directly, use the calculated sample,

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

if your counter is a 'rate' type sample, then you will need to get two samples,

CounterSample sample1 = counter.NextSample();
Thread.Sleep(1000); // wait some time
CounterSample sample2 = counter.NextSample();
float value = CounterSample.Calculate(sample1, sample2);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文