Get disk time in percentage in windows

Viewed 39

I have the following scenario, I want to get the utilization (Disk Time) per disk in percent. Unfortunately it always returns the value 0 when I switch through the instances, why?

Here is my code:

while (true)
{
    foreach (var disk in DriveInfo.GetDrives())
    {
        var diskInstances = diskCounterCategory.GetInstanceNames();
        var diskInstance = string.Empty;

        foreach(var instance in diskInstances)
        {
            if (instance.Contains(disk.Name[0].ToString()))
            {
                var tesst = new PerformanceCounter("PhysicalDisk", "% Disk Time", instance);
                var tesst3 = (uint)tesst.NextSample().BaseValue;
                Console.WriteLine(tesst3);
            }
        }
    }

    Thread.Sleep(1000);
}
1 Answers

I had the same issue. Here is the solution I came up with:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main()
        {
            Console.WriteLine("Setting up the counters...");
            Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
            Dictionary<string, PerformanceCounter> diskCounters = new Dictionary<string, PerformanceCounter>();
            PerformanceCounterCategory logicalDiskCategory = PerformanceCounterCategory.GetCategories().FirstOrDefault(x => x.CategoryName.Equals("LogicalDisk"));
            if (logicalDiskCategory == null)
            {
                Console.WriteLine("ERROR: Category not found!");
                return;
            }
            string[] diskInstances = logicalDiskCategory.GetInstanceNames();
            foreach (string diskName in diskInstances)
            {
                PerformanceCounter counter = logicalDiskCategory.GetCounters(diskName).FirstOrDefault(x => x.CounterName.Equals("% Disk Time"));
                if (counter != null)
                {
                    diskCounters.Add(diskName, counter);
                }
            }
            while (true)
            {
                Console.Clear();
                foreach (KeyValuePair<string, PerformanceCounter> pair in diskCounters)
                {
                    Console.WriteLine($"Time: {DateTime.Now.ToString("HH:mm:ss")}\t| Disk: {pair.Key}\t| Utilisation: {pair.Value.NextValue()}%");
                }
                Thread.Sleep(1000);
            }
        }
    }
}

Explanation:

When we create a counter on our own, like this:

new PerformanceCounter("LogicalDisk", "% Disk Time", "C:");

it will constantly return 0. I myself don’t know why this is so, but if we take PerformanceCounterCategory from the PerformanceCounterCategory.GetCategories() array and then find the desired counter in it through GetCounters(DiskName), the counter will start to produce non-zero results!

But there is one issue in here. If you try to check the names of the Categories you got from the PerformanceCounterCategory.GetCategories() they will be localized, so it is very important to set the Thread.CurrentThread.CurrentCulture to en-US before accessing it, because in other case it will not work at all or will not work on others computers.

Hope this helped)

Related