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の英語版へのアクセス権を持っているので、ローカライズされたバージョンに精度を保証することはできません。この記事を編集することで発生したバグを修正してください。
英語の名前を渡すのがほとんどの場合、ドイツ語のシステムでテストされているようです。しかし、私たちはその英語のカウンターを見つけることができなかったいくつかのスイスシステムを持っていました。 – thomai