2015-11-19 5 views
5

異なるローカリゼーションのシステムで動作するアプリケーションの "Processor Time%"カウンタにアクセスします。PerformanceCounterをインデックスで取得する

これを行うには、そのインデックスで一意であることが保証されているインデックスでカウンタにアクセスしたい(https://support.microsoft.com/en-us/kb/287159参照)。

次のコードは、私はまた、カウンターのカテゴリ名(PerformanceCounterクラスのコンストラクタを参照)と同様にインスタンス名必要動作し、私の現在のロケールで正しい結果が得られますが、パフォーマンスカウンタを開くには:

[DllImport("pdh.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
internal static extern UInt32 PdhLookupPerfNameByIndex(string szMachineName, uint dwNameIndex, StringBuilder szNameBuffer, ref uint pcchNameBufferSize); 

void Main() 
{ 
    var buffer = new StringBuilder(1024); 
    var bufSize = (uint)buffer.Capacity; 
    PdhLookupPerfNameByIndex(null, 6, buffer, ref bufSize); 
    Console.WriteLine(buffer.ToString()); 

    var counter = new PerformanceCounter(/* category??? */, buffer.ToString(), /* instance??? */); 
} 

カテゴリとインスタンス名はどのように取得できますか?

他も参照してください: Retrieve performance counter value in a language-independent wayこれは同じ問題を説明していますが解決策を提供しません。

答えて

6

PdhLookupPerfNameByIndex()がどのように動作するか誤解しています。パフォーマンスカウンターをマップするのではなく、ストリングをマップすることです。カウンターのカテゴリーとその名前の両方に使用する必要があります。カウンターのインスタンスではなく、該当する場合はローカライズされていません。

Regedit.exeを使用することで最も効果的な方法を知ることができます。 HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Perflibに移動します。 "009"キーに注意してください、そのカウンター値は英語の文字列へのインデックスのマッピングを持っています。カウンターをダブルクリックし、ボックスの内容をテキストエディターにコピー&ペーストして、より見やすくします。 "CurrentLanguage"キーは同じマッピングですが、ローカライズされた名前を使用します。

したがって、PdhLookupPerfNameByIndex()はCurrentLanguageキーを使用します。前の手順で取得したリストを使用して、文字列のインデックス番号を確認します。 KB記事の末尾に記載されている(紛らわしい)別の方法は、最初に "009"レジストリキーからインデックス番号を検索することです。これにより、英語の文字列をローカライズされた文字列に変換できます。 KBの記事でレジストリキーの場所が間違っていることが書かれていることに注意してください。

KB記事で指摘されているように、これらのマッピングは「ベース」カウンタにのみ存在し、一部のインデックスが同じ文字列にマップされるため「009」キーがあいまいです。ローカライズされたWindows版のテストは非常に重要です。

それを両方の方法を行いますいくつかのコード:

using System; 
using System.Collections.Generic; 
using System.Text; 
using Microsoft.Win32; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 

public static class PerfMapper { 
    private static Dictionary<string, int> English; 
    private static Dictionary<int, string> Localized; 

    public static PerformanceCounter FromEnglish(string category, string name, string instance = null) { 
     return new PerformanceCounter(Map(category), Map(name), instance); 
    } 

    public static PerformanceCounter FromIndices(int category, int name, string instance = null) { 
     return new PerformanceCounter(PdhMap(category), PdhMap(name), instance); 
    } 

    public static bool HasName(string name) { 
     if (English == null) LoadNames(); 
     if (!English.ContainsKey(name)) return false; 
     var index = English[name]; 
     return !Localized.ContainsKey(index); 
    } 

    public static string Map(string text) { 
     if (HasName(text)) return Localized[English[text]]; 
     else return text; 
    } 

    private static string PdhMap(int index) { 
     int size = 0; 
     uint ret = PdhLookupPerfNameByIndex(null, index, null, ref size); 
     if (ret == 0x800007D2) { 
      var buffer = new StringBuilder(size); 
      ret = PdhLookupPerfNameByIndex(null, index, buffer, ref size); 
      if (ret == 0) return buffer.ToString(); 
     } 
     throw new System.ComponentModel.Win32Exception((int)ret, "PDH lookup failed"); 
    } 

    private static void LoadNames() { 
     string[] english; 
     string[] local; 
     // Retrieve English and localized strings 
     using (var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)) { 
      using (var key = hklm.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009")) { 
       english = (string[])key.GetValue("Counter"); 
      } 
      using (var key = hklm.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\CurrentLanguage")) { 
       local = (string[])key.GetValue("Counter"); 
      } 
     } 
     // Create English lookup table 
     English = new Dictionary<string, int>(english.Length/2, StringComparer.InvariantCultureIgnoreCase); 
     for (int ix = 0; ix < english.Length - 1; ix += 2) { 
      int index = int.Parse(english[ix]); 
      if (!English.ContainsKey(english[ix + 1])) English.Add(english[ix + 1], index); 
     } 
     // Create localized lookup table 
     Localized = new Dictionary<int, string>(local.Length/2); 
     for (int ix = 0; ix < local.Length - 1; ix += 2) { 
      int index = int.Parse(local[ix]); 
      Localized.Add(index, local[ix + 1]); 
     } 
    } 

    [DllImport("pdh.dll", CharSet = CharSet.Auto)] 
    private static extern uint PdhLookupPerfNameByIndex(string machine, int index, StringBuilder buffer, ref int bufsize); 
} 

使用例:

class Program { 
    static void Main(string[] args) { 
     var ctr1 = PerfMapper.FromEnglish("Processor", "% Processor Time"); 
     var ctr2 = PerfMapper.FromIndices(238, 6); 
    } 
} 

私は、Windowsの英語版へのアクセス権を持っているので、ローカライズされたバージョンに精度を保証することはできません。この記事を編集することで発生したバグを修正してください。

0

は、この方法を試してください。

var counter = new PerformanceCounter("Processor", "% Processor Time", "_Total"); 

それはドイツのローカライズでPC上で私のために動作します。

UPDATE

これは、あなたがこれらのカテゴリ、インスタンス、およびカウンタが編成されているかを理解するために使用できる例です。 パフォーマンスモニタのチェックを忘れないでください。の管理ツールコントロールパネルここでカウンタを追加したり、既存のカウンタを見つけることができます。

string counterName = buffer.ToString(); 
PerformanceCounter counter = null;    
foreach (var category in PerformanceCounterCategory.GetCategories()) 
{ 
    // Get all possible instances for the current category 
    var instanceNames = category.GetInstanceNames(); 
    if (instanceNames.Length == 0) 
     continue; 
    // Get all counters in the category. 
    // We want to find an instance with underscores first, for example, "_Total"    
    var counters = category.GetCounters(
     category.GetInstanceNames().OrderBy(i => i).First()); 
    foreach (var currentCounter in counters) 
    {           
     if (currentCounter.CounterName == counterName) 
     { 
      // Hurray! Here it is! 
      counter = currentCounter; 
     } 
    } 
} 
+0

英語の名前を渡すのがほとんどの場合、ドイツ語のシステムでテストされているようです。しかし、私たちはその英語のカウンターを見つけることができなかったいくつかのスイスシステムを持っていました。 – thomai

関連する問題