17
votes

I am currently looking for a way to get the current CPU/RAM/Disk usage in a C# web application using .NET CORE.

For CPU and ram usage, I use PerformanceCounter Class from System.Diagnostics. These are the codes:

 PerformanceCounter cpuCounter;
 PerformanceCounter ramCounter;

 cpuCounter = new PerformanceCounter();

cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";

ramCounter = new PerformanceCounter("Memory", "Available MBytes");


public string getCurrentCpuUsage(){
        cpuCounter.NextValue()+"%";
}

public string getAvailableRAM(){
        ramCounter.NextValue()+"MB";
}

For disk usage, I use the DriveInfo class. These are the codes:

 using System;
 using System.IO;

 class Info {
 public static void Main() {
    DriveInfo[] drives = DriveInfo.GetDrives();
    foreach (DriveInfo drive in drives) {
        //There are more attributes you can use.
        //Check the MSDN link for a complete example.
        Console.WriteLine(drive.Name);
        if (drive.IsReady) Console.WriteLine(drive.TotalSize);
    }
  }
 }

Unfortunately .NET Core does not support DriveInfo and PerformanceCounter classes, hence the codes above do not work.

Does anyone know how I can get the current CPU/RAM/Disk usage in a C# web application using .NET CORE?

3
Is P/Invoke in .NET core? I'm not 100% ramped up on coreclr, yet, but if you have P/Invoke and can call native Windows libs, there is a way to do it.Thumper

3 Answers

4
votes

Processor information is available via System.Diagnostics:

var proc = Process.GetCurrentProcess();
var mem = proc.WorkingSet64;
var cpu = proc.TotalProcessorTime;
Console.WriteLine("My process used working set {0:n3} K of working set and CPU {1:n} msec", 
    mem / 1024.0, cpu.TotalMilliseconds);

DriveInfo is available for Core by adding the System.IO.FileSystem.DriveInfo package

3
votes

You can use PerformnceCounter in the System.Diagnostics.PerformanceCounter package

for example, the next code will give you the total processor usage percent

var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total",true);
var value = cpuCounter.NextValue();
//Note: In most cases you need to call .NextValue() twice to be able to get the real value
if (Math.Abs(value) <= 0.00)
    value = cpuCounter.NextValue();

Console.WriteLine(value);

you can do the same for all OS registered Performance Counters.


Update:

I'm not sure if there is something I should do after creating a new instance of the PerformanceCounter class, but sometimes when I get the next value it comes as 0.

So I've decided to make one instance of PerformanceCounter in at the application level.

e.g.

public static class DiagnosticHelpers
{
    public static float SystemCPU { get; private set; }
    private static readonly object locker = new object();


    static DiagnosticHelpers()
    {
        SystemCPU = 0;
        Task.Run(() =>
        {
            var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total", true);
            while (true)
            {
                Thread.Sleep(1000);
                lock (locker)
                {
                    SystemCPU = cpuCounter.NextValue();
                }
            }
        });
    }
}
2
votes

For Windows i'm using this

var   memorielines= GetWmicOutput("OS get FreePhysicalMemory,TotalVisibleMemorySize /Value").Split("\n");

        var freeMemory= memorielines[0].Split("=", StringSplitOptions.RemoveEmptyEntries)[1];
        var totalMemory = memorielines[1].Split("=", StringSplitOptions.RemoveEmptyEntries)[1];


        var cpuLines = GetWmicOutput("CPU get Name,LoadPercentage /Value").Split("\n");


        var CpuUse = cpuLines[0].Split("=", StringSplitOptions.RemoveEmptyEntries)[1];
        var CpuName = cpuLines[1].Split("=", StringSplitOptions.RemoveEmptyEntries)[1];



    private string GetWmicOutput(string query, bool redirectStandardOutput = true)
    {
        var info = new ProcessStartInfo("wmic");
        info.Arguments = query;
        info.RedirectStandardOutput = redirectStandardOutput;
        var output = "";
        using (var process = Process.Start(info))
        {
            output = process.StandardOutput.ReadToEnd();
        }
        return output.Trim();
    }

For the disk infos you can use this query :

LOGICALDISK get Caption,DeviceID,FileSystem,FreeSpace,Size /Value

if you want a better output formatting give a look to this article : https://www.petri.com/command-line-wmi-part-3