Хорошо, поэтому я в основном пытаюсь создать список установленных категорий счетчиков производительности, например тот, который вы получаете в PerfMon. Для этого я использую
System.Diagnostics.PerformanceCounterCategory.GetCategories()
который, похоже, работает, пока вы не проверите список и не узнаете, что некоторые из них отсутствуют. Первым, что я заметил, был кеш ReadyBoost. Это было связано с тем, что проект был настроен на компиляцию на "x86". Изменение этого параметра на "Любой процессор" исправило эту проблему.
Однако все еще есть некоторые из них, которые отсутствуют, например, одна из тестовых машин имеет категорию "Приложения для диспетчера авторизации" (у меня нет, и никто, кажется, не знает, почему и откуда она). Однако эта машина, эта категория счетчиков производительности отображается в PerfMon, но не при вызове метода 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, как представляется, не является конструктором, который принимает только имя (потому что это не уникально), и, похоже, не существует того, которое принимает значение индекса. Я обнаружил API Win32 с именем Performance Data Helper, но у меня, похоже, нет той функциональности, в которой я хочу. Так. Если у меня есть индекс производительности, как мне, на С# получить 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();
}
}
}
На моей машине я получаю 138 с использованием .Net framework, 117 путем разбора реестра и 157 с помощью PowerShell (что является правильным ответом).
Однако в зависимости от пользователя, у которого установлен PowerShell/Windows SDK, это не вариант.
У кого-нибудь есть идеи вообще? Есть ли какие-то сверхсекретные версии счетчиков производительности, скрытые где-то еще в реестре, что мне нужно отслеживать? У меня не просто есть идеи, чтобы попытаться, у меня не хватало плохих идей, чтобы попробовать. Есть ли какие-либо секретные ключи командной строки, которые я могу использовать для perfmon, чтобы отобразить список всех категорий?