好的,所以我基本上是在尝试创建一个已安装性能计数器类别的列表,就像您在 PerfMon 中获得的那样。为此,我正在使用
System.Diagnostics.PerformanceCounterCategory.GetCategories()
这似乎有效,直到您检查列表并发现其中一些丢失。我发现的第一个缺失是 ReadyBoost Cache。这是因为项目设置为在“x86”上编译。将其更改为“任何 CPU”可以解决该问题。
但是仍然缺少一些,例如,其中一台测试机器具有“授权管理器应用程序”类别(我的没有,而且似乎没有人知道为什么,或者它来自哪里)但是,在那台机器上,该性能计数器类别显示在 PerfMon 中,但在GetCategories()
从 C# 调用该方法时不显示。
有谁知道为什么?有没有更靠谱的获取方式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 的用户,这并不是一个真正的选择。
有人有什么想法吗?是否有一些隐藏在注册表中其他地方的绝密版本 3 性能计数器类别需要我追踪?我不仅没有尝试的想法,而且也没有尝试的坏想法。我可以在 perfmon 上使用任何秘密命令行开关,让它列出所有类别吗?