2013-04-10 5 views
14

さて、基本的にPerfMonで取得したような、インストール済みのパフォーマンスカウンタカテゴリのリストを作成しようとしています。このために私はあなたがリストを検査し、一部が欠けていることを知るまでは、作品のように思えるPerformanceCounterCategory.GetCategoriesはPerfmonと矛盾しています

System.Diagnostics.PerformanceCounterCategory.GetCategories() 

を使用しています。私が見つからなかった最初のものは、ReadyBoostキャッシュでした。これはプロジェクトが "x86"でコンパイルされているためです。これを「Any CPU」に変更すると、その問題が修正されました。

しかし、テストマシンの1つに「認可マネージャアプリケーション」カテゴリがあります(私はそうではなく、誰もなぜ、どこから来たのか分からないようです)。しかし、パフォーマンスカウンタカテゴリがPerfMonで表示されますが、C#からGetCategories()メソッドを呼び出すときには表示されません。

誰でも知っていますか? 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のコンストラクタは存在せず、インデックス値を取るものもないようです。私はパフォーマンスデータヘルパーと呼ばれるWin32 APIを発見しましたが、これは私が望む機能を持っていないようです。そう。パフォーマンスカウンターインデックスがある場合、C#でそのインデックスのPerformanceCounterCategoryを取得するにはどうすればよいですか? PerfMonはそれを行うので、可能でなければなりません。インデックス "マジックナンバー"を解析して、どちらがどれであるか把握する方法はありますか?

EDIT 2

わかりました。 、私は.NET Frameworkを使用して138を取得し、私のマシンで

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(); 
     } 
    } 
} 

117によって:。だから、これはで提案3つの異なるアプローチ(.NET /レジストリ/ PowerShellを)使用してコードの最新バージョンを私の頭をしていますレジストリの解析、157 PowerShell(これは正しい答えです)を使用します。

ただし、PowerShell/Windows SDKをインストールしたユーザーによっては、実際にはオプションではありません。

誰もが考えていますか?レジストリのどこかに隠されている、私が追跡する必要がある、極秘のバージョン3のパフォーマンスカウンタカテゴリがありますか?私は試しにアイデアがなくなっただけでなく、私も悪いアイデアを使い果たしてしまった。 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)。

PerformanceCounterCategory.GetCategories()内部的に働く方法は、最初に "不変の文化"カテゴリをチェックすることです。 が見つかった場合、はこのセットを返します。したがって、何らかのエラーや仕入先の監視のためにカテゴリが1つの言語でしか利用できない場合は、現在の言語設定(OSまたはアプリケーション、またはその両方)に応じてカテゴリを取得できません。

まず、HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\<langcode>\Counterキーの内容を確認して、欠落しているカテゴリがそのいずれかにしかないかどうかを確認します。関連する問題はthis (Google search)であるかもしれませんが、私はさらに確認していません。

率直に言えば、利用可能なカウンタのリストを取得するための「より良い」方法はわかりません。あなたの問題が上記の(または関連する)ものである場合、私はむしろ状況を修正するために見てみたいと思います。

+0

これにより、結果がさらに少なくなります。問題の編集を参照してください。 –

2

私は、Perflib v2のカウンタによって引き起こされる.NET Frameworkのバグとして認定されていると思います。

背景の下でPerformanceCounterCategoryは、Registry Functionsを使用して、パフォーマンスサブシステムに現在登録されているカテゴリ(別名オブジェクト)、インスタンス、およびカウンタに関する情報を取得します。これを確認するには、のコードをILSpyで調べます。

カウンタは、「コア」プロバイダと「拡張性」プロバイダの2種類のプロバイダを通じて登録できます。これらの名前は、より良い選択肢の欠如のために私によって発明されました。

コアプロバイダは、プロセス、システムなどのカウンターを提供するために、パフォーマンスのサブシステムと密接に連携しています。PerformanceCounterCategoryによってこの種のカウンターを見ることができない場合は、あなたのWindowsインストールに深刻な問題があり、イベントログに少なくともthese errorsのいくつかがあります。私はこれがあなたの場合ではないと仮定します。

拡張性プロバイダは、他のすべてのカウンタを提供するために、文書番号Perflib interfaceを使用してパフォーマンスサブシステムと接続します。一部のWindows機能のカウンタは、SQL Server、.NET Frameworkなどの主要なMS製品のカウンタと同様、拡張性プロバイダを介して登録されていることに注意することが重要です。したがって、MSが提供するすべてのものと拡張性第三者のための提供者。

Perflibを通じて登録されたPerformanceCounterCategoryカウンターを見ることができない場合は、最初にプロバイダがシステムに正しく設定されていないか、設定が破損している可能性があります。この場合、パフォーマンスカウンタの読み込みまたはパフォーマンスライブラリの利用可能なセクションで定義されているエラーのいくつかは、イベントログにthese docsから取得する必要があります。私はこれがあなたの場合ではないと仮定します。

第2の理由は、Perflibプロバイダがバックグラウンドでどのように動作するかに関連しています。カウンターを登録するには、2つの大きなステップが必要です。最初の手順は、LodCtr.exeを使用して、レジストリにプロバイダの構成を書き込むことです。私はこれがあなたのためにあなたのために自動的に行われていると仮定します。あなたが関わっているカウンターのインストーラーによって、構成が正しいことが前提です。特に、この構成に問題があった場合、ログ。第2のステップは、実際にPerflibプロバイダをPerformanceサブシステムに登録することです。

今、問題に近づいています。 Perflib v1およびv2プロバイダの登録は非常に異なります。 v1の場合、プロバイダのコードは、手順1で作成されたレジストリ設定から参照され、システム自体によってロードされたDLLに書き込まれます。したがって、Perflib v1プロバイダの登録は、システムがレジストリから設定情報を読み込み、DLLをロードするときに自動的に行われます。 Perflib v2プロバイダでは、状況が異なります。プロバイダのコードは、システムによって直接実行されるのではなく、プロバイダに関連付けられたアプリケーション/サービスによって実行されます。したがって、Perflib v2を使用してカスタムプロバイダ/カウンタを作成するアプリケーションを作成する場合、アプリケーションはこれらのプロバイダのデータを収集するためのコードも実行し、文書化された方法でパフォーマンスサブシステムとインターフェースします。問題は、Perflib v2プロバイダをシステムに登録するコードは、(Perflib v1のようにシステムによって自動的に起動されるのではなく)プロバイダコードをホストするアプリケーションによってトリガされる必要があることです。したがって、たとえば、アプリケーションがWindowsサービスで、サービスがまだ開始していない場合、プロバイダはPerformanceサブシステムに登録されず、カウンタはレジストリ関数/ PerformanceCounterCategoryによって(まだ)表示されません。

Hereは、PerflibではV2プロバイダのため、この自己登録を記述したドキュメントの関連する部分である:

あなたのプロバイダはCounterInitializeとCounterCleanup関数を呼び出す必要があります。 CounterInitializeは、PerfStartProvider関数を呼び出してプロバイダを登録し、PerfSetCounterSetInfo関数を呼び出してカウンタセットを初期化します。 CounterCleanupはPerfStopProvider関数を呼び出して、プロバイダの登録を削除します。

結論として、には、カテゴリ、インスタンス、およびカウンタの2つの異なる方法があります。 1つは、レジストリ関数を照会し、照会時に登録されたすべての項目をリストすることです。もう1つは、クエリ時にPerformanceサブシステムに登録されているかどうかにかかわらず、プロバイダを記述するレジストリに記述された構成情報を調べることです。

実際には、レジストリ関数を照会することによってカテゴリのインスタンスしか取得できないため、構成を照会してまだ登録されていないプロバイダのカテゴリとカウンタのみを取得できるため、2つの方法のコンボを使用する必要がありますレジストリに書かれています。

残念ながら、PerformanceCounterCategoryはレジストリ関数だけを照会するため、まだ登録されていないPerflib v2プロバイダに関する情報は取得できません。これらのプロバイダーは、たとえば、パフォーマンスモニターMMC(登録されているカウンターと登録されていないカウンターの組み合わせを表示できるPDH APIを使用しています)またはtypeperf.exe -qxなど、他の手段で見ることができます。

上記の内容はBranchCacheカテゴリでテストできます。

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

あなたは何のエラーを取得していないとに書き込ま21必要があります。例を以下に表示名BranchCacheとWindowsサービスが開始してから、このC#のコードを実行されていることを確認し勝利7に

  1. を試験しましたデバッグ出力。

  2. BranchCacheサービスを停止して、C#コードを再度実行してください。カテゴリがもはやパフォーマンスサブシステムに登録されていないので、PerformanceCounterCategoryが見つからないため、例外が発生します。私が説明したものを確実にするために

はあなたがPerformanceCounterCategory.GetCategories()経由で行方不明のカウンターに適用され、不足しているカウンターはどこかHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers下のレジストリで設定プロバイダに関連付けられた名前を持つカテゴリにtypeperf -qxによって示されていることを確認してください。

解決策は、PDH APIのC#ラッパーを作成し、その方法で情報を取得することです。特に、ネイティブのやりとりを扱うことに慣れていない場合は、これは自明ではありません。 WMIも有効なオプションのようです(私はPowerShellを使ってパフォーマンスオブジェクトを簡単にリストアップしようとしましたが、すべてのプロバイダのカウンタが返されます)。しかし、ネイティブコードとのインターフェイス方法を知る必要はありませんが、WMI、これも重要ではない。

関連する問題