INFO: Retrieving Counter Data from the Registry |
Q107728
The performance data begins with a structure of type PERF_DATA_BLOCK and is
followed by PERF_DATA_BLOCK.NumObjectTypes data blocks. Each data block
begins with a structure of type PERF_OBJECT_TYPE, followed by
PERF_OBJECT_TYPE.NumCounters structures of type PERF_COUNTER_DEFINITION.
Next, there are PERF_OBJECT_TYPE.NumInstances structures of type
PERF_INSTANCE DEFINITION, each directly followed by an instance name, a
structure of type PERF_COUNTER_BLOCK and PERF_OBJECT_TYPE.NumCounters
counters. All of these data types are described in WINPERF.H.
On Windows NT 4.0 and Win2000, a simpler way to access performance data is to use the PDH.DLL (Performance Data Helper Library). For more information see the Platform SDK document in Base Service, Performance Monitoring, Performance Data, The PDH Interface.
The following steps are used to retrieve all of the counter information from the registry:
#include <windows.h>
#include <stdio.h>
#include <malloc.h>
#define TOTALBYTES 8192
#define BYTEINCREMENT 1024
void main()
{
PPERF_DATA_BLOCK PerfData = NULL;
PPERF_OBJECT_TYPE PerfObj;
PPERF_INSTANCE_DEFINITION PerfInst;
PPERF_COUNTER_DEFINITION PerfCntr, CurCntr;
PPERF_COUNTER_BLOCK PtrToCntr;
DWORD BufferSize = TOTALBYTES;
DWORD i, j, k;
// Allocate the buffer.
PerfData = (PPERF_DATA_BLOCK) malloc( BufferSize );
while( RegQueryValueEx( HKEY_PERFORMANCE_DATA,
"Global",
NULL,
NULL,
(LPBYTE) PerfData,
&BufferSize ) == ERROR_MORE_DATA )
{
// Get a buffer that is big enough.
BufferSize += BYTEINCREMENT;
PerfData = (PPERF_DATA_BLOCK) realloc( PerfData, BufferSize );
}
// Get the first object type.
PerfObj = (PPERF_OBJECT_TYPE)((PBYTE)PerfData +
PerfData->HeaderLength);
// Process all objects.
for( i=0; i < PerfData->NumObjectTypes; i++ )
{
printf( "\nObject: %ld\n", PerfObj->ObjectNameTitleIndex );
// Get the counter block.
PerfCntr = (PPERF_COUNTER_DEFINITION) ((PBYTE)PerfObj +
PerfObj->HeaderLength);
if( PerfObj->NumInstances > 0 )
{
// Get the first instance.
PerfInst = (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfObj +
PerfObj->DefinitionLength);
// Retrieve all instances.
for( k=0; k < PerfObj->NumInstances; k++ )
{
printf( "\n\tInstance: %S\n", (char *)((PBYTE)PerfInst +
PerfInst->NameOffset) );
CurCntr = PerfCntr;
// Get the first counter.
PtrToCntr = (PPERF_COUNTER_BLOCK)((PBYTE)PerfInst +
PerfInst->ByteLength);
// Retrieve all counters.
for( j=0; j < PerfObj->NumCounters; j++ )
{
printf("\t\tCounter: %ld\n",CurCntr->CounterNameTitleIndex);
// Data is (LPVOID)((PBYTE)PtrToCntr + CurCntr->CounterOffset);
// Get next counter.
CurCntr = (PPERF_COUNTER_DEFINITION)((PBYTE)CurCntr +
CurCntr->ByteLength);
}
// Get the next instance.
PerfInst = (PPERF_INSTANCE_DEFINITION)((PBYTE)PtrToCntr +
PtrToCntr->ByteLength);
}
}
else
{
// Get the first counter.
PtrToCntr = (PPERF_COUNTER_BLOCK) ((PBYTE)PerfObj +
PerfObj->DefinitionLength );
// Retrieve all counters.
for( j=0; j < PerfObj->NumCounters; j++ )
{
printf( "\tCounter: %ld\n", PerfCntr->CounterNameTitleIndex );
// Data is (LPVOID)((PBYTE)PtrToCntr + PerfCntr->CounterOffset);
PerfCntr = (PPERF_COUNTER_DEFINITION)((PBYTE)PerfCntr +
PerfCntr->ByteLength);
}
}
// Get the next object type.
PerfObj = (PPERF_OBJECT_TYPE)((PBYTE)PerfObj +
PerfObj->TotalByteLength);
}
}
Note that the instance names are retrieved in a fashion that is similar to
retrieving the data.
RegOpenKeyEx( HKEY_LOCAL_MACHINE,
"Software\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009",
0,
KEY_READ,
&Hkey);
Note that 009 is a language ID, so this value will be different on a
non-English version of the operating system.
RegQueryInfoKey(
Hkey,
(LPTSTR) Class,
&ClassSize,
NULL,
&Subkey,
MaxSubKey,
&MaxClass,
&Values,
&MaxName,
&MaxData,
&SecDesc,
&LastWriteTime );
TitlesDataBase = (PSTR) malloc( (MaxData+1) * sizeof(TCHAR) )
RegQueryValueEx( Hkey,
(LPTSTR) "Counters",
NULL,
NULL,
(LPBYTE) TitlesDataBase,
&MaxData );
RegQueryValueEx( HKEY_PERFORMANCE_DATA,
Indices,
NULL,
NULL,
PerfData,
&BufferSize );
Note that the only difference here is that instead of specifying "Global"
as the second parameter, you specify a string that represents the decimal
value(s) for the object(s) of interest that are obtained from the titles
database.
The PVIEWER and PERFMON samples in the MSTOOLS\SAMPLES\SDKTOOLS\WINNT
directory contain complete sample code that deals with performance data.
For more information, please see the "Performance Overview" in the Win32
SDK documentation and the volume titled "Optimizing Windows NT" in the
Windows NT Resource Kit. The PERFMON sample is now removed from the Platform SDK.
For more information see the Platform SDK documentation in Base Services, Performance Monitoring, Performance Data, The Registry Interface.
Additional query words: 3.10 3.50 Perfmon
Keywords : kbKernBase kbOSWin2000 kbPerfMon kbDSupport kbGrpDSKernBase
Issue type : kbinfo
Technology : kbAudDeveloper kbWin32sSearch kbWin32API
|
Last Reviewed: October 27, 2000 © 2001 Microsoft Corporation. All rights reserved. Terms of Use. |