Итак, я в основном пытаюсь создать список установленных категорий счетчиков производительности, например, тот, который вы получаете в PerfMon. Для этого я используюPerformanceCounterCategory.GetCategories несовместим с Perfmon
System.Diagnostics.PerformanceCounterCategory.GetCategories()
, который кажется, что он работает, пока вы не осмотрите список и не узнаете, что некоторые из них отсутствуют. Первым, что я заметил, был кеш ReadyBoost. Это было связано с тем, что проект был настроен на компиляцию на «x86». Изменение этого параметра на «Любой процессор» исправило эту проблему.
Однако, некоторые из них отсутствуют, например, на одной из тестовых машин есть категория «Приложения для диспетчера авторизации» (у меня нет, и никто, кажется, не знает, почему и откуда она) на этой машине эта группа показателей производительности отображается в PerfMon, но не при вызове метода GetCategories()
из C#.
Кто-нибудь знает, почему? Есть ли более надежный способ получить PerformanceCounterCategories
? Это потому, что я использую .Net? Есть ли какой-то собственный API, который я могу использовать вместо этого?
EDIT
Мне очень жаль, я до сих пор не понимаю. Я написал этот код, чтобы лучше его проиллюстрировать:
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, но у меня, похоже, нет той функциональности, в которой я хочу. Так. Если у меня есть индекс производительности, как мне, на C# получить PerformanceCounterCategory, для этого индекса? PerfMon делает это, поэтому это должно быть возможно. Есть ли способ проанализировать индекс «Магический номер», чтобы выяснить, что это такое?
EDIT 2
Хорошо. Так что это делает мою голову в последнюю версию кода с использованием трех различных подходов, предложенных (.Net/Реестр/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, 117 по разбор реестра и 157 с помощью PowerShell (что является правильным ответом).
Однако в зависимости от пользователя, имеющего установленный PowerShell/Windows SDK, это не вариант.
У кого-нибудь есть идеи вообще? Есть ли какие-то сверхсекретные версии счетчиков производительности, скрытые где-то еще в реестре, что мне нужно отслеживать? У меня не просто есть идеи, чтобы попытаться, у меня не хватало плохих идей, чтобы попробовать. Есть ли какие-либо секретные ключи командной строки, которые я могу использовать на perfmon, чтобы заставить его перечислить все категории?
Я нашел этот фрагмент PowerShell 'Get-Counter -listSet * | Select-Object -ExpandProperty Paths' (источник: http://blogs.msdn.com/b/powershell/archive/2009/04/21/v2-quick-tip-monitoring-performance-counters-with-powershell.aspx) , –
Спасибо. Но мне нужно сделать это программно. Что еще более важно, я не могу полагаться на конечного пользователя, у которого установлен PowerShell. У меня нет PowerShell. :) –