Search code examples
c#cpu-usageperformancecounter

How can I get performance counter to work without getting the user to rebuild with lodctr in a command prompt?


I have been trying to get the total CPU usage of windows PC (Windows 7 running .Net 4.5) in C#. It looks like using PerformanceCounter should be able to meet my needs.

I wrote some trial code based on the three links below (and checking the MSDN pages), this was the most basic version:

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

namespace EntropyProject
{
    class Program
    {
        static void Main(string[] args)
        {
            PerformanceCounter cpuCounter;

            cpuCounter = new PerformanceCounter();
            cpuCounter.CategoryName = "Processor";
            cpuCounter.CounterName = "% Processor Time";
            cpuCounter.InstanceName = "_Total";

            while(true)
            {
                try
                {
                    float firstValue = cpuCounter.NextValue();
                    System.Threading.Thread.Sleep(500);
                    Console.WriteLine("Before getting processor:");
                    float currentCpuUsage = cpuCounter.NextValue();
                    Console.WriteLine("After getting processor:");
                    System.Threading.Thread.Sleep(1000); 
                    Console.WriteLine(currentCpuUsage);
                }
                catch (Exception e)
                {
                    Console.WriteLine("\n{0}\n", e.Message);
                }

                System.Threading.Thread.Sleep(10000);
            }
        }
    }
}

Whenever NextValue is called the exception error below is triggered. This appears to be a common problem with an issue with performance counter values.

Cannot load Counter Name data because an invalid index '' was read from registry

Most recommended solutions suggest that you rebuild the corrupted items using lodctr in a raised command window as admin. However, I was wanting to use the PerformanceCounters in a program that would be released to a large number of people and so would be inappropriate to expect them to rebuild their PerformanceCounters using the command window.

Questions:

  1. Why is this exception error occurring?
  2. How do you properly use PerformanceCounter otherwise?
  3. How can I avoid getting my program users to have to open a cmd window and rebuild their performance counters?

Sources:

  1. How to get CPU usage in C

  2. Get current cpu utilisation in

  3. How can I get the total CPU usage?

Similar Question about the error when accessing counter name asked by Annie Sheikh


Solution

  • According to the documentation for PerformanceCounter.NextValue, "To read performance counters, you must have administrative privileges." The docs also state that an UnauthorizedAccessException will be thrown if "Code that is executing without administrative privileges attempted to read a performance counter."

    But this is a lie. On my Windows 7 environment (64-bit Home Premium edition), running .NET 4.5, I can run your code just fine from a non-raised cmd shell on an Administrator account, or a Standard User account, or even a Guest account.

    If you are running into a privilege problem, then most likely no amount of registry fiddling is going to allow your code to run reliably for all users. But I'm unclear why your code works fine on a Guest account with no admin privileges, given what the documentation says.

    Another option would be to run "wmic.exe cpu get loadpercentage" and parse the output, as suggested in this answer. Based on my testing this works from either an Administrator or Standard User account, but not from a Guest account.