Si interpreta erroneamente come funziona PdhLookupPerfNameByIndex(). Il suo compito non è quello di mappa un contatore delle prestazioni, ma per mappare una stringa. Dovrebbe essere usato sia per la categoria del contatore sia per il suo nome. Non per l'istanza del contatore, se applicabile, non è localizzato.
miglior modo per vedere ciò che fa è quello di utilizzare Regedit.exe. Passare a HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Perflib. Nota il tasto "009", il suo valore Counter ha l'indice per la mappatura delle stringhe in inglese. Fai doppio clic su Contatore e copia e incolla il contenuto della scatola in un editor di testo per avere un aspetto migliore. La chiave "CurrentLanguage" ha lo stesso mapping ma utilizza i nomi localizzati.
Quindi PdhLookupPerfNameByIndex() utilizza la chiave CurrentLanguage, utilizzare l'elenco ottenuto nel passaggio precedente per conoscere il numero di indice della stringa. L'altro modo per farlo come indicato (in modo confuso) nella parte inferiore dell'articolo della Knowledge Base è innanzitutto la ricerca del numero di indice dalla chiave di registro "009". Questo ti permette di tradurre dalla stringa inglese alla stringa localizzata. Si noti che l'articolo della Knowledge Base riporta la posizione della chiave del Registro di sistema errata, nessuna idea del perché.
Ricordare che non è perfetto, come indicato nell'articolo della Knowledge Base, queste mappature esistono solo per i contatori "di base" e il tasto "009" è ambiguo perché alcuni indici si associano alla stessa stringa. Il test su una versione localizzata di Windows è molto importante.
Alcuni codice che fa entrambe le cose: l'utilizzo
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);
}
Esempio:
class Program {
static void Main(string[] args) {
var ctr1 = PerfMapper.FromEnglish("Processor", "% Processor Time");
var ctr2 = PerfMapper.FromIndices(238, 6);
}
}
ho solo l'accesso a una versione inglese di Windows in modo non può garantire per la precisione in una versione localizzata . Correggi qualsiasi bug che incontri modificando questo post.
Sembra che il passaggio dei nomi inglesi funzioni la maggior parte del tempo (anche testato su sistemi tedeschi). Ma avevamo alcuni sistemi svizzeri che non erano in grado di trovare quei segnalini inglesi. – thomai