2013-04-10 5 views
14

Итак, я в основном пытаюсь создать список установленных категорий счетчиков производительности, например, тот, который вы получаете в 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, чтобы заставить его перечислить все категории?

+2

Я нашел этот фрагмент 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) , –

+0

Спасибо. Но мне нужно сделать это программно. Что еще более важно, я не могу полагаться на конечного пользователя, у которого установлен PowerShell. У меня нет PowerShell. :) –

ответ

1

Счетчики производительности (и категории) регистрируются для каждого региона. То есть вы можете иметь разные имена для них в зависимости от языка.

Все доступные категории производительности и их счетчики зарегистрированы в реестре Windows под кодом HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib. Вы найдете дополнительный ключ для каждого доступного языка (например,009 для английского языка).

Метод внутренней работы - это сначала проверить категории «инвариантная культура». Если он найдет любой, он вернёт этот комплект. Таким образом, если из-за некоторой ошибки или недосмотра поставщика категория доступна только на одном языке, вы не получите ее в зависимости от вашего текущего языкового параметра (либо ОС, либо приложения, либо и того и другого).

Сначала я должен проверить содержимое ключей HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\<langcode>\Counter и посмотреть, может быть, недостающая категория находится только в одном из них. Связанная с этим проблема может быть this (Google search), но я еще не проверял.

Честно говоря, я не знаю «лучшего» способа получить список доступных счетчиков. Если ваша проблема - это описанная выше (или связанная), я скорее попытаюсь увидеть, чтобы ситуация была исправлена.

+0

Это дает еще меньше результатов. См. Редактирование в вопросе. –

2

Я думаю, вы столкнулись с тем, что я квалифицирую как ошибку .NET Framework, вызванную счетчиками Perflib v2.

За кулисами PerformanceCounterCategory использует Registry Functions для получения информации об категориях (также называемых объектами), экземплярах и счетчиках, зарегистрированных в настоящее время в подсистеме Performance. Вы можете проверить это, просмотрев код для PerformanceCounterCategory с помощью ILSpy.

Счетчики могут регистрироваться через двух типов поставщиков: «основные» -провайдеры и «расширяемость» -провайдеры. Эти имена были придуманы мной из-за отсутствия лучшего варианта.

Core-провайдеры встроены в Windows и взаимодействуют с подсистемой Performance, чтобы обеспечить счетчики, такие как Process, System и т. Д. Если вы не можете видеть этот счетчик через PerformanceCounterCategory, это очень вероятно у вас есть некоторые проблемы с установкой Windows и по крайней мере некоторые из these errors в ваших журналах событий. Я предполагаю, что это не ваше дело.

Интерфейс расширяемости-провайдера с подсистемой Performance через документированный Perflib interface для предоставления всех других счетчиков. Важно отметить, что счетчики для некоторых функций Windows регистрируются через распространители-распространители, а также счетчики для основных продуктов MS, таких как SQL Server, .NET Framework и т. Д. Таким образом, это не то, что основные поставщики - это все, что сделано MS и расширяемость -провайдеры для третьих сторон.

Если вы не можете просмотреть через PerformanceCounterCategory счетчики, зарегистрированные через Perflib, сначала может быть, что их провайдер неправильно настроен в системе или что конфигурация была повреждена. В этом случае вы должны иметь в своем журнале событий некоторые ошибки, определенные в разделах «Доступность производительности» или «Доступность библиотеки производительности» от these docs. Я предполагаю, что это не ваше дело.

Вторая причина связана с тем, как поставщики Perflib работают за кулисами. Для регистрации своих счетчиков требуются два основных шага. Первый шаг - написать конфигурацию для поставщиков в Реестре, используя LodCtr.exe. Я предполагаю, что это было сделано автоматически для вас установщиками счетчиков, в которые вы заинтересованы, и что конфигурация правильная, тем более, что если возникли проблемы с этой конфигурацией, скорее всего, некоторые из вышеупомянутых ошибок в событии Журнал. Второй шаг - фактически зарегистрировать поставщика Perflib подсистемой Performance.

Теперь мы приближаемся к проблеме. Регистрация выполняется по-разному для поставщиков Perflib v1 и v2. Для v1 код для провайдеров записывается в DLL, на которые ссылается конфигурация реестра, написанная на первом шаге, и загружается самой системой.Таким образом, регистрация провайдера Perflib v1 происходит автоматически, когда система считывает информацию о конфигурации из реестра и загружает библиотеки DLL. Для поставщиков Perflib v2 все по-другому. Код для поставщиков больше не выполняется непосредственно системой, а приложением/службой, связанными с поставщиками. Поэтому, если вы пишете приложение, которое создает пользовательские поставщики/счетчики, используя Perflib v2, ваше приложение также запускает код для сбора данных для этих поставщиков, и он будет взаимодействовать с подсистемой Performance документированным способом. Проблема заключается в том, что код, выполняющий регистрацию поставщиков Perflib v2 с системой, теперь должен запускаться приложением, на котором размещается код провайдера (в отличие от автоматического запуска системы как для Perflib v1). Например, если приложение является сервисом Windows, а служба еще не запущена, поставщики не будут зарегистрированы в подсистеме Performance, и их счетчики не будут показываться через функции реестра/PerformanceCounterCategory.

Here является соответствующей частью документа, описывающей этой саморегистрация для PerfLib v2 провайдеров:

Вашего провайдер должен вызывать функции CounterInitialize и CounterCleanup. CounterInitialize вызывает функцию PerfStartProvider для регистрации провайдера, а также вызывает функцию PerfSetCounterSetInfo для инициализации набора счетчиков. CounterCleanup вызывает функцию PerfStopProvider для удаления регистрации провайдера.

В заключение, есть два различных способа категории листинга, экземпляров и счетчики. Один из них - запрос функций реестра и список всех элементов, зарегистрированных во время запроса. Другой - посмотреть информацию о конфигурации, записанную в реестре, описывающую поставщиков независимо от того, зарегистрированы они или нет в подсистеме Performance во время запроса.

На практике вам нужно будет использовать комбинацию из двух способов, потому что вы можете получать экземпляры только для категорий, запрашивая функции реестра, и вы можете получать только категории и счетчики для поставщиков, которые еще не зарегистрированы, запросив конфигурацию написанных в реестре.

К сожалению, PerformanceCounterCategory запрашивает только функции реестра и поэтому не может предоставить вам информацию о поставщиках Perflib v2, которые еще не зарегистрированы. Вы можете видеть этих поставщиков с помощью других средств, например, через Performance Monitor MMC (который за кулисами использует API PDH, который может показывать комбо зарегистрированных и еще не зарегистрированных счетчиков) или typeperf.exe -qx.

Вы можете проверить это применимо к категории BranchCache. В приведенном ниже примере был протестирован на Win 7.

  1. Обеспечить службы Windows с Отображаемое имя BranchCache запускается, а затем запустить этот C# код:

    Debug.WriteLine((new PerformanceCounterCategory("BranchCache")).ReadCategory().Keys.Count); 
    

    Вы не должны получить ошибок нет и 21 записывается в вывод отладки.

  2. Теперь остановите службу BranchCache и запустите код C# еще раз. Вы получите исключение, так как категория больше не регистрируется в подсистеме «Производительность» и поэтому PerformanceCounterCategory не находит ее.

Для того, что я описал относится к счетчикам вы пропустили через PerformanceCounterCategory.GetCategories(), убедитесь, что отсутствуют счетчики показаны typeperf -qx по категориям с названиями, связанными с поставщиками, сконфигурированных в реестре где-то под HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers.

Решение состоит в том, чтобы написать обертку C# для PDH API и получить вашу информацию таким образом. Это нетривиально, особенно если вы не привыкли к работе с родными взаимодействиями. WMI также является допустимым вариантом (я попробовал быстрый список объектов производительности через PowerShell, и кажется, что возвращаются счетчики для всех поставщиков), но пока вам не нужно знать, как взаимодействовать с собственным кодом, вам нужно знать WMI, что также нетривиально.

 Смежные вопросы

  • Нет связанных вопросов^_^