카운터 이름 및 도움말 텍스트 검색
성능 데이터에는 등록된 각 개체 및 카운터의 이름과 도움말 텍스트를 찾는 데 사용하는 인덱스 값이 포함됩니다. ko-KR: ObjectNameTitleIndex 및 ObjectHelpTitleIndex 멤버는 각각 개체 이름 및 도움말 텍스트에 대한 인덱스 값을 포함하며, PERF_OBJECT_TYPE 구조체의 일부입니다. CounterNameTitleIndex 및 CounterHelpTitleIndex 멤버에는 각각 카운터 이름과 도움말 텍스트에 대한 인덱스 값이 포함되어 있으며, 이는 PERF_COUNTER_DEFINITION 구조체의 일부입니다.
이름 또는 도움말 텍스트를 검색하려면 RegQueryValueEx 함수를 호출합니다. hKey 매개 변수를 다음 미리 정의된 키 중 하나로 설정합니다. 일반적으로 HKEY_PERFORMANCE_NLSTEXT 키를 사용하므로 사용자의 언어 식별자를 확인할 필요가 없습니다.
열쇠 | 묘사 |
---|---|
HKEY_PERFORMANCE_DATA |
lpValueName 매개 변수에 지정한 언어 식별자 값을 기반으로 문자열을 쿼리합니다.
lpValueName 매개 변수를 "Counter <langid>" 또는 "help <langid>"로 설정하여 이름이나 도움말 텍스트를 각각 검색합니다. 여기서 "<langid>"는 0으로 패딩된 3자리 16진수 형식의 시스템 언어 식별자입니다. 언어 식별자는 선택 사항입니다. 언어 식별자를 지정하지 않으면 함수는 영어 문자열을 반환합니다.
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Perflib 레지스트리 키에서 시스템에서 사용할 수 있는 언어 목록을 확인합니다.대부분의 언어로 텍스트를 검색하려면 기본 언어 식별자만 지정합니다. 예를 들어 영어 문자열을 검색하려면 영어-미국 언어 식별자를 1033이 아닌 009로 지정합니다. 중국어 및 포르투갈어 텍스트를 검색하려면 기본 및 하위 언어 식별자를 모두 지정합니다. Windows Server 2003 및 Windows XP: 포르투갈어의 기본 언어 식별자만 지정합니다. Windows 10: "도움말 <langid>" 사용자 지정 언어 식별자가 있는 텍스트는 항상 영어로 문자열을 반환하지만 앞서 언급한 키를 사용하여 레지스트리에서 지역화된 값을 검색할 수 있습니다. |
HKEY_PERFORMANCE_NLSTEXT | 현재 사용자의 기본 UI 언어를 기반으로 문자열을 쿼리합니다. lpValueName 매개 변수를 "Counter" 또는 "Help"로 설정하여 이름이나 도움말 텍스트를 각각 검색합니다. |
HKEY_PERFORMANCE_TEXT | 영어 문자열을 쿼리합니다. lpValueName 매개 변수를 "Counter" 또는 "Help"로 설정하여 이름이나 도움말 텍스트를 각각 검색합니다. |
함수는 데이터를 문자열 목록으로 반환합니다. 각 문자열은 null로 종료됩니다. 마지막 문자열 뒤에 추가 null 종결자가 추가됩니다. 문자열은 쌍으로 나열됩니다. 각 쌍의 첫 번째 문자열은 인덱스이고 두 번째 문자열은 인덱스와 연결된 텍스트입니다. 카운터 데이터는 짝수 인덱스만 사용하고 도움말 데이터는 홀수 인덱스를 사용합니다. 쌍은 인덱스가 증가하는 순서대로 반환됩니다.
다음 목록에서는 카운터 및 도움말 데이터의 예를 보여 줍니다. 지정된 카운터의 인덱스 값을 하나씩 증가하면 카운터의 도움말 텍스트에 대한 인덱스가 제공됩니다. 예를 들어 7은 카운터 인덱스 6과 연결된 도움말 인덱스입니다.
카운터 데이터 쌍.
- 2 시스템 4 메모리 6 % 프로세서 시간
데이터 쌍을 지원합니다.
- 3 시스템 개체 형식에는 해당 카운터들이 포함됩니다 ... 5 메모리 개체 형식에는 해당 카운터들이 포함됩니다 ... 7 프로세서 시간은 비율로 표시됩니다 ...
카운터 데이터의 첫 번째 문자열 쌍은 카운터 이름을 식별하지 않으며 무시할 수 있습니다. 첫 번째 쌍의 인덱스 번호는 1이고 문자열은 시스템 카운터의 최대 인덱스 값을 나타내는 숫자 문자열입니다.
공급자가 이름과 도움말 텍스트를 로드하는 방법에 대한 자세한 내용은 레지스트리 카운터 이름 및 설명 추가참조하세요.
텍스트에 카운터 또는 성능 개체를 식별하는지 여부를 나타내는 정보가 텍스트에 없습니다. 이를 확인하는 유일한 방법 또는 카운터와 개체 간의 관계는 성능 데이터 자체를 쿼리하는 것입니다. 예를 들어 사용자 인터페이스에 개체 및 해당 카운터 목록을 표시하려면 성능 데이터를 검색한 다음 인덱스 값을 사용하여 문자열의 텍스트 데이터를 구문 분석해야 합니다. 이 작업을 수행하는 예제는 개체, 인스턴스 및 카운터 이름 표시을 참조하세요.
다음 예제에서는 HKEY_PERFORMANCE_NLSTEXT를 사용하여 카운터와 도움말 텍스트를 검색하고, 후속 액세스를 위한 테이블을 작성하는 방법을 보여 줍니다.
#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]);
}
}
}
다음 예제에서는 HKEY_PERFORMANCE_DATA 사용하여 카운터 텍스트를 검색하는 방법을 보여줍니다.
#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]);
}
}
}