HOWTO: Access the Performance Registry Under Windows 95Last reviewed: October 3, 1997Article ID: Q174631 |
The information in this article applies to:
SUMMARYWindows 95 comes with an application called System Monitor (Sysmon.exe) that provides users with a method to monitor system resources or performance data. Note that Sysmon.exe is not installed by default under Windows 95, but users can install it via the Control Panel applet named Add/Remove Programs, clicking the Windows Setup tab, and then selecting the System Monitor check box. System resources exist as a collection of objects where an object is a grouping of resources. Each resource within an object can be monitored and is known as a counter. Each object and counter form a unique pair from which performance data is collected. All the information required to perform System Monitor functionality is located in the Windows 95 registry. The process for writing a Performance Monitor involves the following steps:
MORE INFORMATIONStep 1: Determine What Performance Objects Are Currently Active in the SystemTo determine which objects are active in the system, start by enumerating the following registry key:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\control\PerfStats\EnumEach registry key that is listed under this location is called an Object (for example, VFAT, KERNEL, etc.). The availability of objects is dynamic. Therefore, this location must be checked first before proceeding to collect performance data. The following sample code illustrates this concept:
Sample Code
#include <windows.h> #include <stdio.h> #define DIFFFLAGLEN 6 #define PERFENUMKEY "System\\CurrentControlSet\\Control\\PerfStats\\Enum" char szCounter[MAX_PATH]; char szObject[MAX_PATH]; char szName[MAX_PATH]; LPSTR lpszDescBuff = NULL; char szDiffFlag[DIFFFLAGLEN]; // can contain either "TRUE" or "FALSE" void main(void) { DWORD rc; DWORD dwIndex1, dwIndex2; DWORD dwType; DWORD dwBufSize; HKEY hKey; HKEY hObject; HKEY hCounter; rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, PERFENUMKEY, 0, KEY_READ, &hKey); if (rc == ERROR_SUCCESS) { dwBufSize = MAX_PATH; dwIndex1 = 0; // enumerate objects while ( RegEnumKeyEx(hKey, dwIndex1++, szObject, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS ) { if ( (rc=RegOpenKeyEx(hKey, szObject, 0, KEY_READ, &hObject)) == ERROR_SUCCESS) { // process information on the open key using hObject } RegCloseKey(hObject); dwBufSize = MAX_PATH; } RegCloseKey(hKey); } else printf("Error %d opening %s\n", rc, PERFENUMKEY); } // end main Step 2: Determine the Characteristics of Each Performance ObjectEach performance object key is characterized by one registry value. This registry value is of type REG_SZ and is called "Name." The "Name" registry key identifies the commonly used name of the object (for example, VFAT is know as "File System"). It is this "Name" that would be shown to an end user that is using the system monitor application. Use RegQueryValueEx() to obtain this registry value as shown in the following sample code:
Sample Code
if ((rc=RegQueryValueEx(hObject, "Name", NULL, &dwType, szObject, &dwBufSize)) == ERROR_SUCCESS) { } Step 3: Determine what Performance Counters Are Active for Each perf ObjectAssociated with each performance object key identified above with hObject, there is one or more performance counters. Each performance counter exists as a subkey of a performance object key. The following sample code enumerates all these performance counters for a given performance object (hObject):
Sample Code
// enumerate counters dwIndex2 = 0; dwBufSize = MAX_PATH; while(RegEnumKeyEx(hObject, dwIndex2++, szCounter, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { if ( (rc=RegOpenKeyEx(hObject, szCounter, 0, KEY_READ, &hCounter)) == ERROR_SUCCESS) { // do processing on open counter key using hCounter } else printf("Error %d opening counter %s\n", rc, szCounter); RegCloseKey(hCounter); dwBufSize = MAX_PATH; } Step 4: Determine the Characteristics of Each Performance CounterSimilar to a performance object, each performance counter is characterized by three registry values. Each of these registry values is identified by "Name" and is of type REG_SZ. This "Name" value identifies the commonly used name of the counter (for example, CPUUsage is know as "Processor Usage (%)") and would be displayed to a user. A second REG_SZ value called "Description" describes the counter in more detail. You can use this description to provide more detail to the user. And finally, there is a third REG_SZ value called "Differentiate" that is either "TRUE" or "FALSE." If "Differentiate" is set to "FALSE" then the data retrieved is used in its raw form. If "Differentiate" is "TRUE" the data retrieved for this counter must be differentiated over time as follows:
Counter_Value2 - Counter_Value1 ----------------------------------------- Time_Taken2 - Time_Taken1The following code illustrates this procedure:
Sample Code
// First, get the Name of the performance counter dwBufSize = MAX_PATH; rc = RegQueryValueEx(hObject, "Name", NULL, &dwType, szName, &dwBufSize); // Second, get the Description dwBufSize = 0; RegQueryValueEx(hCounter, "Description", NULL, &dwType, NULL, &dwBufSize); lpszDescBuff = LocalAlloc(LPTR, dwBufSize + 1); rc = RegQueryValueEx(hCounter, "Description", NULL, &dwType, lpszDescBuff, &dwBufSize); if (ERROR_SUCCESS == rc) { printf("%s: %s\n", szCounter, lpszDescBuff); LocalFree(lpszDescBuff); } // get the Differentiate value dwBufSize = DIFFFLAGLEN; rc = RegQueryValueEx(hCounter, "Differentiate", NULL, &dwType, szDiffFlag, &dwBufSize); if (ERROR_SUCCESS == rc) { printf("Differentiating Counter: %s\n\n", szDiffFlag); } Step 5: Enable the Collection of Performance DataTogether, the performance object key name and counter subkey name pair is used to initialize performance data collection. To request the beginning of a performance data collection for any performance object\counter pair, use the object\counter pair to query the registry value located at HKEY_DYN_DATA\PerfStats\StartStat using RegQueryValueEx. For example, to start performance data collection on KERNEL\CPUUsage, a registry query on KERNEL\CPUUsage at location HKEY_DYN_DATA\PerfStats\StartStat is performed. If no requests to start data collection are issued, the performance data retrieved for KERNEL\CPUUsage is always 100%. Once a request to start performance data collection is issued, the data retrieved reflects the actual CPU utilization.
Sample Code
BOOL EnableDataCollection(char *szObjName, char *szCounterName) { HKEY hOpen; DWORD cbData; DWORD dwType; LPBYTE pByte; DWORD rc; char *szCounterData; BOOL bSuccess = TRUE; if ( (rc = RegOpenKeyEx(HKEY_DYN_DATA,"PerfStats\\StartStat", 0, KEY_READ, &hOpen)) == ERROR_SUCCESS) { // concatenate the object and couter key names szCounterData = LocalAlloc(LPTR, lstrlen(szObjName) + lstrlen(szCounterName) + 2); wsprintf(szCounterData, "%s\\%s", szObjName, szCounterName); // query to get data size if ( (rc = RegQueryValueEx(hOpen,szCounterData,NULL,&dwType, NULL, &cbData )) == ERROR_SUCCESS ) { pByte = LocalAlloc(LPTR, cbData); // query the performance start key to initialize performance data // query the start key to initialize performance data rc = RegQueryValueEx(hOpen,szCounterData,NULL,&dwType, pByte, &cbData ); // at this point we don't do anything with the data // free up resources LocalFree(pByte); } else bSuccess = FALSE; CloseHandle(hOpen); LocalFree(szCounterData); } else bSuccess = FALSE; return bSuccess; } Step 6: Retrieve Performance Data for an object\counter PairOnce performance data collection is initialized, each performance object key and counter subkey pair is again used to retrieve performance data from the registry key HKEY_DYN_DATA\PerfStats\StartData using RegQueryValueEx (for example, KERNEL\CPUUsage, KERNEL\Threads, etc.). The performance data retrieved using RegQueryValueEx is always of type DWORD (for example, 4 bytes).
Sample Code
BOOL CollectPerfData(char *szObjName, char *szCounterName, DWORD *pdwData) { HKEY hOpen; DWORD dwType; DWORD cbData; char *szCounterData; DWORD rc; BOOL bSuccess = TRUE; // concatenate the object and counter keys szCounterData = LocalAlloc(LPTR, lstrlen(szObjName) + lstrlen(szCounterName) + 2); wsprintf(szCounterData, "%s\\%s", szObjName, szCounterName); // open performance data key if ( (rc = RegOpenKeyEx(HKEY_DYN_DATA,"PerfStats\\StatData", 0, KEY_READ, &hOpen)) == ERROR_SUCCESS) { cbData = sizeof(DWORD); // retrieve performance data which is of size of DWORD rc=RegQueryValueEx(hOpen,szCounterData,0,&dwType, (LPBYTE)pdwData,&cbData ); // let the caller know if it worked or not bSuccess = rc == ERROR_SUCCESS; RegCloseKey(hOpen); } else bSuccess = FALSE; // free the resources LocalFree(szCounterData); return bSuccess; } Step 7: Disable the Collection of Performance DataAfter performance data retrieval is completed, performance data collection must be de-initialized or turned off to allow system resources to be released. To request the end of performance data collection for any object\counter pair, the object\counter pair is used to query the registry value located at HKEY_DYN_DATA\PerfStats\StopStat using RegQueryValueEx(). For example, to request performance data collection end for KERNEL\CPUUsage, RegQueryValueEx() is used to query the registry value KERNEL\CPUUsage at location HKEY_DYN_DATA\PerfStats\StopStat.
Sample Code
BOOL DisableDataCollection(char *szObjName, char *szCounterName) { HKEY hOpen; LPBYTE pByte; DWORD cbData; DWORD dwType; DWORD rc; char *szCounterData; BOOL bSuccess = TRUE; if ( (rc = RegOpenKeyEx(HKEY_DYN_DATA,"PerfStats\\StopStat", 0, KEY_READ, &hOpen)) == ERROR_SUCCESS) { // concatenate the object and couter key names szCounterData = LocalAlloc(LPTR, lstrlen(szObjName) + lstrlen(szCounterName) + 2); wsprintf(szCounterData, "%s\\%s", szObjName, szCounterName); // query to get data size if ( (rc = RegQueryValueEx(hOpen,szCounterData,NULL,&dwType, NULL, &cbData )) == ERROR_SUCCESS ) { pByte = LocalAlloc(LPTR, cbData); // query the performance start key to initialize performance data // query the start key to initialize performance data rc = RegQueryValueEx(hOpen,szCounterData,NULL,&dwType, pByte, &cbData ); // at this point we don't do anything with the data // free up resources LocalFree(pByte); } else bSuccess = FALSE; CloseHandle(hOpen); LocalFree(szCounterData); } else bSuccess = FALSE; return bSuccess; } Step 8: Remote System MonitoringSince performance data is part of the registry and since RegConnectRegistry() enables one Windows 95 machine to read and write to a remote registry, system monitoring can be performed on a remote Windows 95 machine. Follow these steps to enable this functionality:
REFERENCESSince performance monitoring is such a valuable tool, Windows 95 has provided a method by which additional performance objects can be added to the registry. In Windows 95, performance data is provided by a collection of VxDs. It is the job of these VxDs to provide the performance data upon request as the registry is queried. To get more information on how to providing performance objects, consult the Device Driver Kit (DDK) documentation. Keywords : BsePerfmon BseRegistry Version : WINNT: Platform : winnt Issue type : kbhowto |
================================================================================
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |