PerformanceCounterCategory.GetCategories与性能监视器不一致监视器、性能、PerformanceCounterCategory、GetCategories

2023-09-04 02:35:40 作者:在蚊帐里裸睡挑逗蚊子

好了,所以我基本上是试图创建安装性能计数器类别的列表,就像你在PerfMon中得到的。对于这个我用

Okay, So I'm basically trying to create a list of installed Performance Counter Categories, like the one you get in PerfMon. For this I'm using

System.Diagnostics.PerformanceCounterCategory.GetCategories()

这似乎是它的工作原理,直到你检查清单,并找出一些缺失。第一个我发现缺少的是ReadyBoost的缓存。这是因为项目设置为编译的x86。更改此为任何CPU解决了问题。

which seems like it works, until you inspect the list, and find out that some are missing. The first one I spotted missing was the ReadyBoost Cache. This was because the project was set to compile on "x86". Changing this to "Any CPU" fixed that issue.

不过还是有一些缺失,比如,测试机器中的一个具有授权管理器应用程序类别(我现在没有,似乎没有人知道为什么,或者来自何方)然而,这台机器,那性能计数器类别显示在性能监视器,但不能从C#调用 GetCategories()方法时。

However there are still some that are missing, for instance, one of the test machines has a "Authorization Manager Applications" Category (mine doesn't, and nobody seems to know why, or where it comes from) However, on that machine, that Performance Counter Category shows up in PerfMon, but not when invoking the GetCategories() method from C#.

有谁知道为什么吗?有没有更可靠的方式来获得 PerformanceCounterCategories ?这是因为我使用的.Net?有一些原生API,我可以用呢?

Does anyone know why? Is there a more reliable way to get PerformanceCounterCategories? Is this because I'm using .Net? Is there some native API I can use instead?

修改

我很抱歉,我还是不明白这一点。我写这个code到也许更能说明它:

I'm sorry, I still don't get it. I've written this code to perhaps better illustrate it:

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这需要只是名字(因为这不是唯一的),也不会似乎有其中一个取索引值。我发现了一个名为性能数据助手的Win32 API,但这似乎并没有我想无论是功能。所以。如果我有一个性能计数器指数,我该怎么办,在C#中获得PerformanceCounterCategory,该指数?性能监视器这样做,所以它必须是可能的。是否有某种方式来分析索引幻数搞清楚哪个是哪个?

This now gives me 3236 results. Because it gets all the performance counters in the system. So I figure all I need to do is filter out those that are actually performance counters, leaving me with just categories. However there does not seem to be a constructor for the PerformanceCounter which takes just the name(because this is not unique), nor does there seem to be one which takes the index value. I've discovered a Win32 API named Performance Data Helper, but this doesn't seem to have the functionality I want either. So. If I have a Performance Counter Index, how do I, in C# get the PerformanceCounterCategory, for that index? PerfMon does it, so it must be possible. Is there some way to parse the Index "Magic Number" to figure out which is which?

编辑2

好。因此,这是做我的头在使用三种不同的方法code提出的最新版本(.NET /注册表/ PowerShell中):

Okay. So this is doing my head in. The latest version of the code using the three different approaches suggested (.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();
        }
    }
}

在我的机器上,我得到138使用.NET Framework,117通过解析注册表,157通过使用PowerShell的(这是正确的答案)。

On my machine I get 138 using the .Net framework, 117 by parsing the registry, and 157 by using PowerShell (which is the correct answer).

不过这取决于用户无需安装PowerShell中/ Windows SDK的是不是一个真正的选择。

However depending on the user having installed PowerShell/Windows SDK is not really an option.

任何人有什么想法呢?是否有一些绝密版本3的性能计数器类别,隐藏在其他地方在注册表中,我需要追查?我不仅江郎才尽去尝试,我的馊主意跑出来,试图为好。是否有任何秘密命令行开关我可以在性能监视器使用,得到它列出所有类别?

Anyone have any ideas at all? Are there some top secret version 3 performance counter categories, hidden somewhere else in the registry, that I need to track down? I've not only run out of ideas to try, I've run out of bad ideas to try as well. Are there any secret command line switches I can use on perfmon, to get it to list all the Categories?

推荐答案

性能计数器(和类别)的每个区域注册。也就是说,你可以有不同的名称,它们依赖于语言。

Performance counters (and categories) are registered per locale. That is, you can have different names for them depending on the language.

所有可用的性能类别和他们的柜台登记在Windows注册表下的 HKLM \ SOFTWARE \微软\的Windows NT \ CURRENTVERSION \内Perflib 。你会发现一个子项为每种可用语言(如 009 为英文)。

All available performance categories and their counters are registered in the Windows Registry under HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib. You will find a sub key for each available language (e.g. 009 for English).

PerformanceCounterCategory.GetCategories()方法在内部工作原理是,首先勾选不变的文化范畴。如果找到的任意的它将返回这一套。所以,如果由于某些错误或供应商的监督一类是只适用于一种语言,你不会得到它取决于你的当前语言设置(无论是操作系统或应用程序,或两者)上。

The PerformanceCounterCategory.GetCategories() method internally works is to first check the "invariant culture" categories. If it finds any it will return this set. So, if due to some error or vendor's oversight a category is only available with one language, you'll not get it depending on your current language setting (either OS or application or both).

我会首先检查 HKLM \ SOFTWARE \微软\的Windows NT \ CURRENTVERSION \内Perflib \&LT的内容;郎code取代; \计数器键,看看如果可能丢失的类是仅在其中的一个。一个相关的问题可能是这个(谷歌搜索),但我还没有进一步的检查。

I would first check the content of the HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\<langcode>\Counter keys and see if maybe the missing category is only in one of them. A related issue might be this (Google search), but I haven't checked further.

坦率地说,我不知道有任何更好的方式获得可用计数器的列表。如果你的问题是上面(或相关)中所描述的,我宁愿尝试看看,以获得固定的情况。

Frankly, I don't know of any "better" way to get the list of available counters. If your issue is the one described above (or related), I would rather try to see to get the situation fixed.