C# – custom performance counter in c# / perfmon

ccounterperfmonperformance

Hi I am trying to to create a custom performance counter for use in perfmon. The following code works pretty well, however I have one problem..

With this solution I have a timer updating the value of the performance counter, however I would like to not have to run this executable to get the data I need. That is I would like to just be able to install the counter as a one time thing and then have perfmon query for the data (as it does with all the pre-installed counters).

How can I achieve this?

using System;
using System.Diagnostics;
using System.Net.NetworkInformation;

namespace PerfCounter
{
class PerfCounter
{
    private const String categoryName = "Custom category";
    private const String counterName = "Total bytes received";
    private const String categoryHelp = "A category for custom performance counters";
    private const String counterHelp = "Total bytes received on network interface";
    private const String lanName = "Local Area Connection"; // change this to match your network connection
    private const int sampleRateInMillis = 1000;
    private const int numberofSamples = 100;

    private static NetworkInterface lan = null;
    private static PerformanceCounter perfCounter;

    static void Main(string[] args)
    {
        setupLAN();
        setupCategory();
        createCounters();
        updatePerfCounters();
    }

    private static void setupCategory()
    {
        if (!PerformanceCounterCategory.Exists(categoryName))
        {
            CounterCreationDataCollection counterCreationDataCollection = new CounterCreationDataCollection();
            CounterCreationData totalBytesReceived = new CounterCreationData();
            totalBytesReceived.CounterType = PerformanceCounterType.NumberOfItems64;
            totalBytesReceived.CounterName = counterName;
            counterCreationDataCollection.Add(totalBytesReceived);
            PerformanceCounterCategory.Create(categoryName, categoryHelp, PerformanceCounterCategoryType.MultiInstance, counterCreationDataCollection);
        }
        else
            Console.WriteLine("Category {0} exists", categoryName);
    }

    private static void createCounters() {
        perfCounter = new PerformanceCounter(categoryName, counterName, false);
        perfCounter.RawValue = getTotalBytesReceived();
    }

    private static long getTotalBytesReceived()
    {
        return lan.GetIPv4Statistics().BytesReceived;
    }

    private static void setupLAN()
    {
        NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
        foreach (NetworkInterface networkInterface in interfaces)
        {
            if (networkInterface.Name.Equals(lanName))
                lan = networkInterface;
        }
    }
    private static void updatePerfCounters()
    {
        for (int i = 0; i < numberofSamples; i++)
        {
            perfCounter.RawValue = getTotalBytesReceived();
            Console.WriteLine("perfCounter.RawValue = {0}", perfCounter.RawValue);
            System.Threading.Thread.Sleep(sampleRateInMillis);
        }
    }
}

}

Best Answer

In Win32, Performance Counters work by having PerfMon load a DLL which provides the counter values.

In .NET, this DLL is a stub which uses shared memory to communicate with a running .NET process. The process periodically pushes new values to the shared memory block, and the DLL makes them available as performance counters.

So, basically, you're probably going to have to implement your performance counter DLL in native code, because .NET performance counters assume that there's a process running.