Listing all performance counters on Windows with C# .NET

Performance counters in Windows can help you with finding bottlenecks in your application. There’s a long range of built-in performance counters in Windows which you can view in the Performance Monitor window:

Performance Monitor window

Right-click anywhere on the larger screen to the right and select Add Counters to add your counters to the graph. The Add Counters window will show the categories first. You can then open a category and select one or more specific counters within that category. The graph will show the real-time data immediately:

Performance Monitor with added pre-built categories

The System.Diagnostics namespace has a couple of objects that let you find the available performance categories and counters on the local machine or on another machine. Each performance category has a name, a help text and a type. It’s straightforward to find the categories available on a machine:

PerformanceCounterCategory[] categories = PerformanceCounterCategory.GetCategories();
foreach (PerformanceCounterCategory category in categories)
{
	Console.WriteLine("Category name: {0}", category.CategoryName);
	Console.WriteLine("Category type: {0}", category.CategoryType);
	Console.WriteLine("Category help: {0}", category.CategoryHelp);
}

GetCategories() has an overload where you can specify a computer name if you’d like to view the counters on another computer within the network.

At the time of writing this post I had 161 categories on my machine. Example:

Name: WMI Objects
Help: Number of WMI High Performance provider returned by WMI Adapter
Type: SingleInstance

Once you got hold of a category you can easily list the counters within it. The below code prints the category name, type and help text along with any instance names. If there are separate instances within the category then we need to called the GetCounters method with the instance name if it exists otherwise we’ll get an exception saying that there are multiple instances.

PerformanceCounterCategory[] categories = PerformanceCounterCategory.GetCategories();
foreach (PerformanceCounterCategory category in categories)
{
	Console.WriteLine("Category name: {0}", category.CategoryName);
	Console.WriteLine("Category type: {0}", category.CategoryType);
	Console.WriteLine("Category help: {0}", category.CategoryHelp);
	string[] instances = category.GetInstanceNames();
	if (instances.Any())
	{
		foreach (string instance in instances)
		{
			if (category.InstanceExists(instance))
			{
				PerformanceCounter[] countersOfCategory = category.GetCounters(instance);
				foreach (PerformanceCounter pc in countersOfCategory)
				{
					Console.WriteLine("Category: {0}, instance: {1}, counter: {2}", pc.CategoryName, instance, pc.CounterName);
				}
			}
		}
	}
	else
	{
		PerformanceCounter[] countersOfCategory = category.GetCounters();
		foreach (PerformanceCounter pc in countersOfCategory)
		{
                	Console.WriteLine("Category: {0}, counter: {1}", pc.CategoryName, pc.CounterName);
		}
	}	
}

Each counter in turn has a name, a help text and a type. E.g. here’s a counter with the “Active Server Pages” category:

Name: Requests Failed Total
Help: The total number of requests failed due to errors, authorization failure, and rejections.
Type: NumberOfItems32

You can view all posts related to Diagnostics here.

Unknown's avatarAbout Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

One Response to Listing all performance counters on Windows with C# .NET

  1. pregunton's avatar pregunton says:

    Do you use performance counters on production IIS web sites?


    <%@ Page Language="C#" AutoEventWireup="true" %>
    <%@ Import Namespace="System" %>
    <%@ Import Namespace="System.Diagnostics" %>
    <%@ Import Namespace="System.Text" %>
    <%@ Import Namespace="System.DirectoryServices" %>
    <%@ Import Namespace="System.Collections.Generic" %>
    <script type="text/C#" runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack)
    {
    populateIIS();
    }
    }
    private void populateIIS()
    {
    StringBuilder sb = new StringBuilder();
    sb.AppendFormat("Server: {0} Username: {1}<br/>", Environment.MachineName.ToString(), Environment.UserName.ToString());
    try
    {
    TimeSpan span = TimeSpan.FromSeconds(Convert.ToDouble(getCounter("Web Service", "Service Uptime", "_Total")));
    sb.Append(string.Concat(new object[] { "IIS Running – Uptime : ", span.Days, " Days, ", span.Hours, " Hours, ", span.Minutes, " Min <br/>" }));
    }
    catch { }
    sb.AppendFormat("Current Anonymous users: {0}<br/>", getCounter("Web Service", "Current Anonymous Users", "_Total"));
    sb.AppendFormat("Current Connections: {0}<br/>", getCounter("Web Service", "Current Connections", "_Total"));
    sb.AppendFormat("Max Connections: {0}<br/>", getCounter("Web Service", "Maximum Connections", "_Total"));
    sb.AppendFormat("Memory, Available MBytes: {0}<hr/>", getCounter("Memory", "Available MBytes", ""));
    sb.AppendFormat("ASP.NET Request Wait Time: {0}<br/>", getCounter("ASP.NET", "Request Wait Time", ""));
    sb.AppendFormat("ASP.NET Application Anonymous Requests: {0}<br/>", getCounter("ASP.NET Applications", "Anonymous Requests", "__Total__"));
    sb.AppendFormat("ASP.NET Sessions Active: {0}<br/>", getCounter("ASP.NET Applications", "Sessions Active", "__Total__"));
    sb.AppendFormat("ASP.NET Sessions Total: {0}<br/>", getCounter("ASP.NET Applications", "Sessions Total", "__Total__"));
    sb.AppendFormat("ASP.NET Applications Running: {0}<hr/>", getCounter("ASP.NET v2.0.50727", "Applications Running", ""));
    sb.Append("IIS Apps <br/>");
    foreach (string s in getIISApps())
    { sb.AppendFormat("{0}", s);}
    lblText.Text = sb.ToString();
    }
    public static string getCounter(string a, string b, string c)
    {
    string countervalue;
    try
    {
    string str = string.Empty;
    PerformanceCounter counter = new PerformanceCounter(a, b);
    counter.InstanceName = c;
    str = counter.NextValue().ToString();
    counter.Dispose();
    counter.Close();
    countervalue = str;
    }
    catch (Exception exception)
    {
    throw exception;
    }
    return countervalue;
    }
    private List<string> getIISApps()
    {
    List<string> sites = new List<string>();
    DirectoryEntry entry = new DirectoryEntry("IIS://" + Environment.MachineName + "/w3svc");
    try
    {
    foreach (DirectoryEntry entry2 in entry.Children)
    {
    if (entry2.SchemaClassName == "IIsWebServer")
    {
    foreach (DirectoryEntry entry3 in entry2.Children)
    {
    string binding;
    if (!(entry3.SchemaClassName == "IIsWebVirtualDir"))
    {
    continue;
    }
    if (entry2.Properties["ServerBindings"].Value.ToString() == "System.Object[]")
    {
    binding = "All Unassigned";
    }
    else
    {
    binding = entry2.Properties["ServerBindings"].Value.ToString();
    }
    sites.Add(string.Format("name: {0} – binding: {1}<br/>", entry2.Properties["ServerComment"].Value.ToString(), binding));
    }
    }
    }
    }
    catch (Exception ex)
    {
    throw ex;
    }
    return sites;
    }
    </script>
    <asp:Label ID="lblText" runat="server" />

    and .NET Data Provider for SQLServer ?

Leave a comment

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

ARCHIVED: Bite-size insight on Cyber Security for the not too technical.