C# C:访问“性能”的性能计数器;。NET CLR内存类别“;

C# C:访问“性能”的性能计数器;。NET CLR内存类别“;,c#,.net,memory,performancecounter,C#,.net,Memory,Performancecounter,我正在尝试使用PerformanceCounter类通过C#访问中的性能计数器。但是,a无法使用我所期望的正确类别/计数器名称实例化类别 new PerformanceCounter(".NET CLR Memory", "# bytes in all heaps", Process.GetCurrentProcess().ProcessName); 我尝试使用以下代码在类别和计数器之间循环 string[] categories = PerformanceCounterCategory.Ge

我正在尝试使用PerformanceCounter类通过C#访问中的性能计数器。但是,a无法使用我所期望的正确类别/计数器名称实例化类别

new PerformanceCounter(".NET CLR Memory", "# bytes in all heaps", Process.GetCurrentProcess().ProcessName);
我尝试使用以下代码在类别和计数器之间循环

string[] categories = PerformanceCounterCategory.GetCategories().Select(c => c.CategoryName).OrderBy(s => s).ToArray();
string toInspect = string.Join(",\r\n", categories);

System.Text.StringBuilder interestingToInspect = new System.Text.StringBuilder();
string[] interestingCategories = categories.Where(s => s.StartsWith(".NET") || s.Contains("Memory")).ToArray();
foreach (string interestingCategory in interestingCategories)
{
    PerformanceCounterCategory cat = new PerformanceCounterCategory(interestingCategory);
    foreach (PerformanceCounter counter in cat.GetCounters())
    {
        interestingToInspect.AppendLine(interestingCategory + ":" + counter.CounterName);
    }
}
toInspect = interestingToInspect.ToString();
但找不到任何匹配的。无法从CLR中观察这些值,或者我做错了什么


如果有必要的话,环境是在64位windows 7设备上运行的.NET 4.0。

计数器是每个实例的计数器。尝试添加:

foreach (var instance in cat.GetInstanceNames())
{
    foreach (PerformanceCounter counter in cat.GetCounters(instance))
    {
        interestingToInspect.AppendLine(interestingCategory + ":" + counter.CounterName); 
    } 
}

它应该会起作用。请注意,正如其他人已经设置的那样,CLR计数器是每个实例的计数器,因此需要为要查询计数器的进程指定实例名称

因此,您在帖子顶部指定的声明应该有效。但是,还应使用构造函数重载,该重载允许您指定希望以“只读”模式访问实例:

您发布的第二个代码片段不起作用,因为您没有为
GetCounters()
操作指定实例名称。使用
GetCounters(string instanceName)
重载,它应该可以工作

最后,请注意,实例名称不一定与
Process.ProcessName
(或
Process.GetCurrentProcess().ProcessName
)相同。如果一个进程有多个实例,即可执行文件,则通过添加
#
来创建进程名称。要计算进程的实际实例名称,应查询
.NET CLR Memory\process ID
计数器

例如:

    public static string GetInstanceNameForProcessId(int pid)
    {
        var cat = new PerformanceCounterCategory(".NET CLR Memory");
        foreach (var instanceName in cat.GetInstanceNames())
        {
            try
            {
                 using (var pcPid = new PerformanceCounter(cat.CategoryName, "Process ID", instanceName))
                 {
                     if ((int)pcPid.NextValue() == pid)
                     {
                         return instanceName;
                     }
                 }
            }
            catch (InvalidOperationException)
            {
                // This may happen, if the PC-instance no longer exists between the
                // time we called GetInstanceNames() and the time we come around actually
                // try and use the instance. 
                // In this situation that is not an error, so ignore it.
            }
        }

        throw new ArgumentException(
            string.Format("No performance counter instance found for process id '{0}'", pid),
            "pid");
    }
通过此方法收集的实例名称也适用于其他“.NET CLR”类别中的性能计数器


更新:增加了收集潜在实例名称和仔细阅读它们之间潜在竞争条件的缓解措施。当我们尝试使用.NET进程(我们已经看到了它的实例名)时,它可能不再存在(这样的实例也消失了)。

您需要以管理员身份运行该程序才能访问.NET CLR内存类别

使用powershell尝试此简单测试:

以管理员身份运行时

[Diagnostics.PerformanceCounterCategory]::存在(“.NET CLR内存”)

真的

在没有管理权限的情况下运行时:

[Diagnostics.PerformanceCounterCategory]::存在(“.NET CLR内存”)

假的


+1是的,最好将此标记为答案,以便于查找。起初我忽略了它,因为它在底部。这是不正确的。具有管理员访问权限就足够了,但您不需要管理员访问权限。请参阅:将您自己添加到Performance Monitor用户组,然后注销并登录。这是否只是一个使用管理员权限运行的情况,如Oleg的回答所示?值得一提的是,原始文章是由Ingo Rammer在@Che中完成的,谢谢。但是,请注意,事实上,我是自己提出上述问题的,在性能计数器等方面做了大量工作。如果问题得到了正确的解决方案,那么许多人会提出“相同”的解决方案也就不足为奇了;-)
    public static string GetInstanceNameForProcessId(int pid)
    {
        var cat = new PerformanceCounterCategory(".NET CLR Memory");
        foreach (var instanceName in cat.GetInstanceNames())
        {
            try
            {
                 using (var pcPid = new PerformanceCounter(cat.CategoryName, "Process ID", instanceName))
                 {
                     if ((int)pcPid.NextValue() == pid)
                     {
                         return instanceName;
                     }
                 }
            }
            catch (InvalidOperationException)
            {
                // This may happen, if the PC-instance no longer exists between the
                // time we called GetInstanceNames() and the time we come around actually
                // try and use the instance. 
                // In this situation that is not an error, so ignore it.
            }
        }

        throw new ArgumentException(
            string.Format("No performance counter instance found for process id '{0}'", pid),
            "pid");
    }