Získávání názvů čítačů a textu nápovědy
Data o výkonu obsahují hodnoty indexu, které používáte k vyhledání názvů a textu nápovědy pro každý zaregistrovaný objekt a čítač. ObjectNameTitleIndex a ObjectHelpTitleIndex členy struktury PERF_OBJECT_TYPE obsahují hodnoty indexu pro název objektu a text nápovědy, a CounterNameTitleIndex a CounterHelpTitleIndex členy struktury PERF_COUNTER_DEFINITION obsahují hodnoty indexu pro název čítače a text nápovědy, respektive.
Pokud chcete načíst názvy nebo text nápovědy, zavolejte funkci RegQueryValueEx. Nastavte parametr hKey na jeden z následujících předdefinovaných klíčů. Obvykle byste použili klíč HKEY_PERFORMANCE_NLSTEXT, takže nemusíte určit identifikátor jazyka uživatele.
Klíč | Popis |
---|---|
HKEY_PERFORMANCE_DATA | Řetězce dotazu založené na hodnotě identifikátoru jazyka, kterou zadáte v parametru lpValueName. Nastavte parametr lpValueName na hodnotu "Counter <langid>" nebo "Help <langid>" pro načtení názvů nebo textu nápovědy, kde "<langid>" je identifikátor jazyka systému formátovaný jako 3ciferné šestnáctkové číslo. Identifikátor jazyka je volitelný. Pokud nezadáte identifikátor jazyka, vrátí funkce anglické řetězce. Seznam jazyků dostupných v systému najdete v klíči registru HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Perflib .Pokud chcete načíst text ve většině jazyků, zadejte pouze identifikátor primárního jazyka. Pokud chcete například načíst anglické řetězce, zadejte identifikátor jazyka jako 009, nikoli 1033 pro angličtinu a USA. Pokud chcete načíst čínský a portugalský text, zadejte primární i dílčí identifikátory. Windows Server 2003 a Windows XP: Zadejte pouze identifikátor primárního jazyka pro portugalštinu. Windows 10: Text "Help <langid>" s vlastním identifikátorem jazyka vždy vrací řetězce v angličtině, i když lokalizovanou hodnotu je možné z registru načíst pomocí výše uvedeného klíče. |
HKEY_PERFORMANCE_NLSTEXT | Řetězce dotazu založené na výchozím jazyce uživatelského rozhraní aktuálního uživatele. Nastavte parametr lpValueName na hodnotu Counter nebo Help pro načtení názvů nebo textu nápovědy. |
HKEY_PERFORMANCE_TEXT | Dotaz na anglické textové řetězce Nastavte parametr lpValueName na hodnotu Counter nebo Help pro načtení názvů nebo textu nápovědy. |
Funkce vrátí data jako seznam řetězců. Každý řetězec je ukončen s hodnotou null. Za posledním řetězcem následuje další ukončovací znak null. Řetězce jsou uvedeny ve dvojicích. Prvním řetězcem každého páru je index a druhým řetězcem je text přidružený k indexu. Údaje čítače používají pouze sudé indexy, zatímco údaje nápovědy používají liché indexy. Páry se vrátí ve zvyšujícím se pořadí indexu.
Následující seznamy ukazují příklady ukazatelů a podpůrných dat. Zvýšením indexové hodnoty daného čítače o jedna obdržíte index textu nápovědy čítače. Například 7 je index nápovědy přidružený k indexu čítače 6.
Páry dat čítačů
- 2 Systém 4 Paměť 6 % doba procesoru
Pomoc s páry dat
- 3 Typ systémového objektu obsahuje tyto čítače, které ... 5 Typ paměťového objektu zahrnuje ty čítače, které ... 7 Doba procesoru je vyjádřena jako procento ...
Všimněte si, že první dvojice řetězců v datech čítače neidentifikuje název čítače a lze jej ignorovat. Číslo indexu prvního páru je 1 a řetězec je číselný řetězec, který představuje maximální hodnotu indexu pro systémové čítače.
Informace o tom, jak poskytovatel načítá název a text nápovědy, najdete v tématu Přidání názvů a popisů čítačůdo registru.
V textu nejsou žádné informace, které označují, zda text identifikuje čítač nebo objekt výkonu. Jediným způsobem, jak to zjistit, nebo vztah mezi čítači a objekty, je dotazovat se na samotná data o výkonu. Pokud například chcete zobrazit seznam objektů a jejich čítačů v uživatelském rozhraní, musíte načíst data o výkonu a pak pomocí hodnot indexu parsovat textová data pro řetězce. Příklad, který to dělá, viz v části Zobrazení názvů objektů, instancí a čítačů.
Následující příklad ukazuje, jak pomocí HKEY_PERFORMANCE_NLSTEXT načíst čítač a text nápovědy a vytvořit tabulku pro následný přístup.
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "advapi32.lib")
LPWSTR GetText(LPWSTR pwszSource);
BOOL BuildTextTable(LPWSTR pCounterHead, LPWSTR pHelpHead, LPDWORD* pOffsetsHead, LPDWORD pNumberOfOffsets);
DWORD GetNumberOfTextEntries(LPWSTR pwszSource);
void PrintCounterAndHelpText(LPWSTR pCounterTextHead, LPWSTR pHelpTextHead, LPDWORD pTextOffsets, DWORD dwNumberOfOffsets);
void wmain(void)
{
LPWSTR pCounterTextHead = NULL; // Head of the MULTI_SZ buffer that contains the Counter text.
LPWSTR pHelpTextHead = NULL; // Head of the MULTI_SZ buffer that contains the Help text.
LPDWORD pTextOffsets = NULL; // Array of DWORDS that contain the offsets to the text in
// pCounterTextHead and pHelpTextHead. The text index
// values mirror the array index.
DWORD dwNumberOfOffsets = 0; // Number of elements in the pTextOffsets array.
pCounterTextHead = GetText(L"Counter");
if (NULL == pCounterTextHead)
{
wprintf(L"GetText(L\"Counter\") failed.\n");
goto cleanup;
}
pHelpTextHead = GetText(L"Help");
if (NULL == pHelpTextHead)
{
wprintf(L"GetText(L\"Help\") failed.\n");
goto cleanup;
}
if (BuildTextTable(pCounterTextHead, pHelpTextHead, &pTextOffsets, &dwNumberOfOffsets))
{
PrintCounterAndHelpText(pCounterTextHead, pHelpTextHead, pTextOffsets, dwNumberOfOffsets);
}
else
{
wprintf(L"BuildTextTable failed.\n");
}
cleanup:
if (pCounterTextHead)
free(pCounterTextHead);
if (pHelpTextHead)
free(pHelpTextHead);
if (pTextOffsets)
free(pTextOffsets);
// You do not need to call RegCloseKey if you are only
// retrieving names and help text.
}
// Get the text based on the source value. This function uses the
// HKEY_PERFORMANCE_NLSTEXT key to get the strings.
LPWSTR GetText(LPWSTR pwszSource)
{
LPWSTR pBuffer = NULL;
DWORD dwBufferSize = 0;
LONG status = ERROR_SUCCESS;
// Query the size of the text data so you can allocate the buffer.
status = RegQueryValueEx(HKEY_PERFORMANCE_NLSTEXT, pwszSource, NULL, NULL, NULL, &dwBufferSize);
if (ERROR_SUCCESS != status)
{
wprintf(L"RegQueryValueEx failed getting required buffer size. Error is 0x%x.\n", status);
goto cleanup;
}
// Allocate the text buffer and query the text.
pBuffer = (LPWSTR)malloc(dwBufferSize);
if (pBuffer)
{
status = RegQueryValueEx(HKEY_PERFORMANCE_NLSTEXT, pwszSource, NULL, NULL, (LPBYTE)pBuffer, &dwBufferSize);
if (ERROR_SUCCESS != status)
{
wprintf(L"RegQueryValueEx failed with 0x%x.\n", status);
free(pBuffer);
pBuffer = NULL;
goto cleanup;
}
}
else
{
wprintf(L"malloc failed to allocate memory.\n");
}
cleanup:
return pBuffer;
}
// Build a table of offsets into the counter and help text buffers. Use the index
// values from the performance data queries to access the offsets.
BOOL BuildTextTable(LPWSTR pCounterHead, LPWSTR pHelpHead, LPDWORD* pOffsetsHead, LPDWORD pNumberOfOffsets)
{
BOOL fSuccess = FALSE;
LPWSTR pwszCounterText = NULL; // Used to cycle through the Counter text
LPWSTR pwszHelpText = NULL; // Used to cycle through the Help text
LPDWORD pOffsets = NULL;
DWORD dwCounterIndex = 0; // Index value of the Counter text
DWORD dwHelpIndex = 0; // Index value of the Help text
DWORD dwSize = 0; // Size of the block of memory that holds the offset array
pwszCounterText = pCounterHead;
pwszHelpText = pHelpHead;
*pNumberOfOffsets = GetNumberOfTextEntries(L"Last Help");
if (0 == *pNumberOfOffsets)
{
wprintf(L"GetNumberOfTextEntries failed; returned 0 for number of entries.\n");
goto cleanup;
}
dwSize = sizeof(DWORD) * (*pNumberOfOffsets + 1); // Add one to make the array one-based
pOffsets = (LPDWORD)malloc(dwSize);
if (pOffsets)
{
ZeroMemory(pOffsets, dwSize);
*pOffsetsHead = pOffsets;
// Bypass first record (pair) of the counter data - contains upper bounds of system counter index.
pwszCounterText += (wcslen(pwszCounterText)+1);
pwszCounterText += (wcslen(pwszCounterText)+1);
for (; *pwszCounterText; pwszCounterText += (wcslen(pwszCounterText)+1))
{
dwCounterIndex = _wtoi(pwszCounterText);
dwHelpIndex = _wtoi(pwszHelpText);
// Use the counter's index value as an indexer into the pOffsets array.
// Store the offset to the counter text in the array element.
pwszCounterText += (wcslen(pwszCounterText)+1); //Skip past index value
pOffsets[dwCounterIndex] = (DWORD)(pwszCounterText - pCounterHead);
// Some help indexes for system counters do not have a matching counter, so loop
// until you find the matching help index or the index is greater than the corresponding
// counter index. For example, if the indexes were as follows, you would loop
// until the help index was 11.
//
// Counter index Help Index
// 2 3
// 4 5
// 6 7
// 9 (skip because there is no matching Counter index)
// 10 11
while (*pwszHelpText && dwHelpIndex < dwCounterIndex)
{
pwszHelpText += (wcslen(pwszHelpText)+1); // Skip past index value
pwszHelpText += (wcslen(pwszHelpText)+1); // Skip past help text to the next index value
dwHelpIndex = _wtoi(pwszHelpText);
}
// Use the Help index value as an indexer into the pOffsets array.
// Store the offset to the help text in the array element.
if (dwHelpIndex == (dwCounterIndex + 1))
{
pwszHelpText += (wcslen(pwszHelpText)+1); //Skip past index value
pOffsets[dwHelpIndex] = (DWORD)(pwszHelpText - pHelpHead);
pwszHelpText += (wcslen(pwszHelpText)+1); //Skip past help text to next index value
}
}
fSuccess = TRUE;
}
cleanup:
return fSuccess;
}
// Retrieve the last help index used from the registry. Use this number
// to allocate an array of DWORDs. Note that index values are not contiguous.
DWORD GetNumberOfTextEntries(LPWSTR pwszSource)
{
DWORD dwEntries = 0;
LONG status = ERROR_SUCCESS;
HKEY hkey = NULL;
DWORD dwSize = sizeof(DWORD);
LPWSTR pwszMessage = NULL;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib",
0,
KEY_READ,
&hkey);
if (ERROR_SUCCESS != status)
{
wprintf(L"RegOpenKeyEx failed with 0x%x.\n", status);
goto cleanup;
}
status = RegQueryValueEx(hkey, pwszSource, NULL, 0, (LPBYTE)&dwEntries, &dwSize);
if (ERROR_SUCCESS != status)
{
wprintf(L"RegQueryValueEx failed with 0x%x.\n", status);
}
cleanup:
if (hkey)
RegCloseKey(hkey);
return dwEntries;
}
// Print the pairs of counter and help text.
void PrintCounterAndHelpText(LPWSTR pCounterTextHead, LPWSTR pHelpTextHead, LPDWORD pTextOffsets, DWORD dwNumberOfOffsets)
{ UNREFERENCED_PARAMETER(dwNumberOfOffsets);
// Counter index values are even numbers that start at 2 so begin with
// the second element of the array of offsets. Many array elements will
// not contain offset values (index values are not contiguous).
// There is typically a large number of counters, so this example prints
// the first 10 counters and help text.
//for (DWORD i = 2; i < (dwNumberOfOffsets+1); i++)
for (DWORD i = 2; i < 22; i++)
{
if (pTextOffsets[i]) // If index offset is not zero
{
if (0 == (i % 2)) // Counter text index (even number)
wprintf(L"%d %s\n", i, pCounterTextHead+pTextOffsets[i]);
else
wprintf(L"%d %s\n\n", i, pHelpTextHead+pTextOffsets[i]);
}
}
}
Následující příklad ukazuje, jak pomocí HKEY_PERFORMANCE_DATA načíst text čítače.
#include <windows.h>
#include <stdio.h>
#include <strsafe.h>
#pragma comment(lib, "advapi32.lib")
LPWSTR GetText(LPWSTR pwszSource);
BOOL BuildTextTable(LPWSTR pCounterHead, LPWSTR pHelpHead, LPDWORD* pOffsetsHead, LPDWORD pNumberOfOffsets);
DWORD GetNumberOfTextEntries(LPWSTR pwszSource);
void PrintCounterAndHelpText(LPWSTR pCounterTextHead, LPWSTR pHelpTextHead, LPDWORD pTextOffsets, DWORD dwNumberOfOffsets);
LANGID GetLanguageId();
void wmain(void)
{
LPWSTR pCounterTextHead = NULL; // Head of the MULTI_SZ buffer that contains the Counter text.
LPWSTR pHelpTextHead = NULL; // Head of the MULTI_SZ buffer that contains the Help text.
LPDWORD pTextOffsets = NULL; // Array of DWORDS that contain the offsets to the text in
// pCounterTextHead and pHelpTextHead. The text index
// values mirror the array index.
DWORD dwNumberOfOffsets = 0; // Number of elements in the pTextOffsets array.
pCounterTextHead = GetText(L"Counter");
if (NULL == pCounterTextHead)
{
wprintf(L"GetText(L\"Counter\") failed.\n");
goto cleanup;
}
pHelpTextHead = GetText(L"Help");
if (NULL == pHelpTextHead)
{
wprintf(L"GetText(L\"Help\") failed.\n");
goto cleanup;
}
if (BuildTextTable(pCounterTextHead, pHelpTextHead, &pTextOffsets, &dwNumberOfOffsets))
{
PrintCounterAndHelpText(pCounterTextHead, pHelpTextHead, pTextOffsets, dwNumberOfOffsets);
}
else
{
wprintf(L"BuildTextTable failed.\n");
}
cleanup:
if (pCounterTextHead)
free(pCounterTextHead);
if (pHelpTextHead)
free(pHelpTextHead);
if (pTextOffsets)
free(pTextOffsets);
// You do not need to call RegCloseKey if you are only
// retrieving names and help text.
}
// Get the text based on the source value. This function uses the
// HKEY_PERFORMANCE_DATA key to get the strings.
LPWSTR GetText(LPWSTR pwszSource)
{
LPWSTR pBuffer = NULL;
DWORD dwBufferSize = 0;
LONG status = ERROR_SUCCESS;
LANGID langid = 0;
WCHAR wszSourceAndLangId[15]; // Identifies the source of the text; either
// "Counter <langid>" or "Help <langid>"
// Create the lpValueName string for the registry query.
langid = GetLanguageId();
if (0 == langid)
{
wprintf(L"GetLanguageId failed to get the default language identifier.\n");
goto cleanup;
}
StringCchPrintf(wszSourceAndLangId, 15, L"%s %03x", pwszSource, langid);
// Query the size of the text data so you can allocate the buffer.
status = RegQueryValueEx(HKEY_PERFORMANCE_DATA, wszSourceAndLangId, NULL, NULL, NULL, &dwBufferSize);
if (ERROR_SUCCESS != status)
{
wprintf(L"RegQueryValueEx failed getting required buffer size. Error is 0x%x.\n", status);
goto cleanup;
}
// Allocate the text buffer and query the text.
pBuffer = (LPWSTR)malloc(dwBufferSize);
if (pBuffer)
{
status = RegQueryValueEx(HKEY_PERFORMANCE_DATA, wszSourceAndLangId, NULL, NULL, (LPBYTE)pBuffer, &dwBufferSize);
if (ERROR_SUCCESS != status)
{
wprintf(L"RegQueryValueEx failed with 0x%x.\n", status);
free(pBuffer);
pBuffer = NULL;
goto cleanup;
}
}
else
{
wprintf(L"malloc failed to allocate memory.\n");
}
cleanup:
return pBuffer;
}
// Retrieve the default language identifier of the current user. For most languages,
// you use the primary language identifier only to retrieve the text. In Windows XP and
// Windows Server 2003, you use the complete language identifier to retrieve Chinese
// text. In Windows Vista, you use the complete language identifier to retrieve Portuguese
// text.
LANGID GetLanguageId()
{
LANGID langid = 0; // Complete language identifier.
WORD primary = 0; // Primary language identifier.
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&osvi))
{
langid = GetUserDefaultUILanguage();
primary = PRIMARYLANGID(langid);
if ( (LANG_PORTUGUESE == primary && osvi.dwBuildNumber > 5) || // Windows Vista and later
(LANG_CHINESE == primary && (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion >= 1)) ) // XP and Windows Server 2003
{
; //Use the complete language identifier.
}
else
{
langid = primary;
}
}
else
{
wprintf(L"GetVersionEx failed with 0x%x.\n", GetLastError());
}
return langid;
}
// Build a table of offsets into the counter and help text buffers. Use the index
// values from the performance data queries to access the offsets.
BOOL BuildTextTable(LPWSTR pCounterHead, LPWSTR pHelpHead, LPDWORD* pOffsetsHead, LPDWORD pNumberOfOffsets)
{
BOOL fSuccess = FALSE;
LPWSTR pwszCounterText = NULL; // Used to cycle through the Counter text
LPWSTR pwszHelpText = NULL; // Used to cycle through the Help text
LPDWORD pOffsets = NULL;
DWORD dwCounterIndex = 0; // Index value of the Counter text
DWORD dwHelpIndex = 0; // Index value of the Help text
DWORD dwSize = 0; // Size of the block of memory that holds the offset array
pwszCounterText = pCounterHead;
pwszHelpText = pHelpHead;
*pNumberOfOffsets = GetNumberOfTextEntries(L"Last Help");
if (0 == *pNumberOfOffsets)
{
wprintf(L"GetNumberOfTextEntries failed; returned 0 for number of entries.\n");
goto cleanup;
}
dwSize = sizeof(DWORD) * (*pNumberOfOffsets + 1); // Add one to make the array one-based
pOffsets = (LPDWORD)malloc(dwSize);
if (pOffsets)
{
ZeroMemory(pOffsets, dwSize);
*pOffsetsHead = pOffsets;
// Bypass first record (pair) of the counter data - contains upper bounds of system counter index.
pwszCounterText += (wcslen(pwszCounterText)+1);
pwszCounterText += (wcslen(pwszCounterText)+1);
for (; *pwszCounterText; pwszCounterText += (wcslen(pwszCounterText)+1))
{
dwCounterIndex = _wtoi(pwszCounterText);
dwHelpIndex = _wtoi(pwszHelpText);
// Use the counter's index value as an indexer into the pOffsets array.
// Store the offset to the counter text in the array element.
pwszCounterText += (wcslen(pwszCounterText)+1); //Skip past index value
pOffsets[dwCounterIndex] = (DWORD)(pwszCounterText - pCounterHead);
// Some help indexes for system counters do not have a matching counter, so loop
// until you find the matching help index or the index is greater than the corresponding
// counter index. For example, if the indexes were as follows, you would loop
// until the help index was 11.
//
// Counter index Help Index
// 2 3
// 4 5
// 6 7
// 9 (skip because there is no matching Counter index)
// 10 11
while (*pwszHelpText && dwHelpIndex < dwCounterIndex)
{
pwszHelpText += (wcslen(pwszHelpText)+1); // Skip past index value
pwszHelpText += (wcslen(pwszHelpText)+1); // Skip past help text to the next index value
dwHelpIndex = _wtoi(pwszHelpText);
}
// Use the Help index value as an indexer into the pOffsets array.
// Store the offset to the help text in the array element.
if (dwHelpIndex == (dwCounterIndex + 1))
{
pwszHelpText += (wcslen(pwszHelpText)+1); //Skip past index value
pOffsets[dwHelpIndex] = (DWORD)(pwszHelpText - pHelpHead);
pwszHelpText += (wcslen(pwszHelpText)+1); //Skip past help text to next index value
}
}
fSuccess = TRUE;
}
cleanup:
return fSuccess;
}
// Retrieve the last help index used from the registry. Use this number
// to allocate an array of DWORDs. Note that index values are not contiguous.
DWORD GetNumberOfTextEntries(LPWSTR pwszSource)
{
DWORD dwEntries = 0;
LONG status = ERROR_SUCCESS;
HKEY hkey = NULL;
DWORD dwSize = sizeof(DWORD);
LPWSTR pwszMessage = NULL;
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib",
0,
KEY_READ,
&hkey);
if (ERROR_SUCCESS != status)
{
wprintf(L"RegOpenKeyEx failed with 0x%x.\n", status);
goto cleanup;
}
status = RegQueryValueEx(hkey, pwszSource, NULL, 0, (LPBYTE)&dwEntries, &dwSize);
if (ERROR_SUCCESS != status)
{
wprintf(L"RegQueryValueEx failed with 0x%x.\n", status);
}
cleanup:
if (hkey)
RegCloseKey(hkey);
return dwEntries;
}
// Print the pairs of counter and help text.
void PrintCounterAndHelpText(LPWSTR pCounterTextHead, LPWSTR pHelpTextHead, LPDWORD pTextOffsets, DWORD dwNumberOfOffsets)
{ UNREFERENCED_PARAMETER(dwNumberOfOffsets);
// Counter index values are even numbers that start at 2 so begin with
// the second element of the array of offsets. Many array elements will
// not contain offset values (index values are not contiguous).
// There is typically a large number of counters, so this example prints
// the first 10 counters and help text.
//for (DWORD i = 2; i < (dwNumberOfOffsets+1); i++)
for (DWORD i = 2; i < 22; i++)
{
if (pTextOffsets[i]) // If index offset is not zero
{
if (0 == (i % 2)) // Counter text index (even number)
wprintf(L"%d %s\n", i, pCounterTextHead+pTextOffsets[i]);
else
wprintf(L"%d %s\n\n", i, pHelpTextHead+pTextOffsets[i]);
}
}
}