好的,所以我基本上是在尝试创建已安装的性能计数器类别的列表,就像在PerfMon中获得的那样。为此,我正在使用

System.Diagnostics.PerformanceCounterCategory.GetCategories()

在您检查列表之前,发现其中有些缺失,这似乎是可行的。我发现缺少的第一个是ReadyBoost缓存。这是因为该项目设置为在“x86”上编译。将其更改为“Any CPU”可解决该问题。

但是,仍然缺少一些东西,例如,其中一台测试计算机具有“Authorization Manager应用程序”类别(我没有,并且似乎没人知道原因或来源)。但是,在该计算机上,性能计数器类别显示在PerfMon中,但从C#调用GetCategories()方法时则不显示。

有人知道为什么吗?有没有更可靠的方法来获取PerformanceCounterCategories?这是因为我使用的是.Net吗?是否可以使用一些本机API?

编辑

对不起,我还是不明白。我编写了以下代码以更好地说明它:
using System;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Win32;

namespace PccHack
{
    class Program
    {
        private static readonly Regex Numeric = new Regex(@"^\d+$");
        static void Main(string[] args)
        {
            var pcc1 = PerformanceCounterCategory.GetCategories();
            Console.Out.WriteLine("Getting automatically from the microsoft framework gave {0} results.", pcc1.Count());
            string[] counters;
            using (var regKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009"))
            {
                counters = regKey.GetValue("Counter") as string[];
            }
            var pcc2 = counters.Where(counter => !Numeric.IsMatch(counter)).ToList();
            pcc2.Sort();
            Console.Out.WriteLine("Getting manually from the registry gave {0} results.", pcc2.Count());
            Console.In.ReadLine();
        }
    }
}

现在这给了我3236个结果。因为它获取系统中的所有性能计数器。所以我想我要做的就是过滤掉那些实际上是性能计数器的东西,只剩下类别。但是,似乎没有一个仅使用名称的PerformanceCounter构造函数(因为这不是唯一的),也似乎没有一个使用索引值的构造函数。我发现了一个名为Performance Data Helper的Win32 API,但这似乎也没有我想要的功能。所以。如果我有性能计数器索引,如何在C#中获取该索引的PerformanceCounterCategory? PerfMon做到了,因此必须可行。有什么方法可以解析索引“幻数”以找出哪个?

编辑2

好的。因此,这是我的主意。建议使用三种不同方法(.Net / Registry / PowerShell)的最新版本代码:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Microsoft.Win32;
using System.Management.Automation;


namespace PccHack
{
    internal class Program
    {
        private static void Main()
        {
            var counterMap = new Dictionary<string, string>();
            using (var regKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009"))
            {
                var counter = regKey.GetValue("Counter") as string[];
                for (var i = 0; i < counter.Count() - 1; i += 2)
                {
                    counterMap.Add(counter[i], counter[i + 1]);
                }
            }

            var pcc1 = PerformanceCounterCategory.GetCategories().Select(o => o.CategoryName).ToList();
            var pcc2 = new List<string>();
            // Get v1 providers
            using (var regKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\services"))
            {
                foreach (var subKeyName in regKey.GetSubKeyNames())
                {
                    using (var subKey = regKey.OpenSubKey(subKeyName))
                    {
                        if (!subKey.GetSubKeyNames().Contains("Performance")) continue;
                        using (var perfKey = subKey.OpenSubKey("Performance"))
                        {
                            var blah = (string) perfKey.GetValue("Object List");
                            if (blah != null)
                            {
                                pcc2.AddRange(blah.Split(' ').Select(b => counterMap[b]));
                            }
                        }
                    }
                }
            }
            // Get v2 providers
            using (var regKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers"))
            {
                foreach (var subKeyName in regKey.GetSubKeyNames())
                {
                    using (var subKey = regKey.OpenSubKey(subKeyName))
                    {
                        foreach (var perfKeyName in subKey.GetSubKeyNames())
                        {
                            using (var perfKey = subKey.OpenSubKey(perfKeyName))
                            {
                                var blah = (string) perfKey.GetValue("NeutralName");
                                if (blah != null)
                                {
                                    pcc2.Add(blah);
                                }
                            }
                        }
                    }
                }
            }
            var ps = PowerShell.Create();

            ps.AddCommand("Get-Counter").AddParameter("listSet", "*");
            var pcc3 = ps.Invoke().Select(result => result.Members["CounterSetName"].Value.ToString()).ToList();

            pcc1.Sort();
            pcc2.Sort();
            pcc3.Sort();
            Console.Out.WriteLine("Getting automatically from the microsoft framework gave {0} results.", pcc1.Count());
            Console.Out.WriteLine("Getting manually from the registry gave {0} results.", pcc2.Count());
            Console.Out.WriteLine("Getting from PowerShell gave {0} results.", pcc3.Count());
            Console.In.ReadLine();
        }
    }
}

在我的机器上,使用.Net框架获得138,通过解析注册表获得117,使用PowerShell产生157(这是正确的答案)。

但是,实际取决于用户是否安装了PowerShell / Windows SDK。

有人有任何想法吗?是否有一些我需要跟踪的顶级 secret 版本3性能计数器类别(隐藏在注册表中的其他位置)?我不仅没有足够的想法去尝试,而且也没有足够的想法去尝试。我可以在perfmon上使用任何 secret 的命令行开关来列出所有类别吗?

最佳答案

性能计数器(和类别)在每个区域中都注册。也就是说,您可以根据语言使用不同的名称。

所有可用的性能类别及其计数器都在Windows注册表中的HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib下注册。您会找到每种可用语言的子键(例如,英语的009)。
PerformanceCounterCategory.GetCategories()方法内部起作用的是首先检查“不变文化”类别。如果找到任何内容,它将返回此集合。因此,如果由于某些错误或供应商的疏忽,类别仅适用于一种语言,则您将无法获得该类别,具体取决于当前的语言设置(操作系统或应用程序或两者)。

我首先要检查HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\<langcode>\Counter键的内容,看看丢失的类别是否仅在其中一个类别中。一个相关的问题可能是this (Google search),但是我没有进一步检查。

坦白说,我不知道要获得可用计数器列表的任何“更好”方法。如果您的问题是上述问题(或相关问题),我希望尝试解决此问题。

10-06 13:53