Attribute VB_Name = "Module1"
'------------------------------------------------------------------------------
' WINPERF.H / PDH.DLL constants and defines
' Matt Pietrek - March 1998 MSJ
'------------------------------------------------------------------------------
Enum PERF_DETAIL
PERF_DETAIL_NOVICE = 100 ' The uninformed can understand it
PERF_DETAIL_ADVANCED = 200 ' For the advanced user
PERF_DETAIL_EXPERT = 300 ' For the expert user
PERF_DETAIL_WIZARD = 400 ' For the system designer
End Enum
Enum PDH_STATUS
PDH_CSTATUS_VALID_DATA = &H0
PDH_CSTATUS_NEW_DATA = &H1
PDH_CSTATUS_NO_MACHINE = &H800007D0
PDH_CSTATUS_NO_INSTANCE = &H800007D1
PDH_MORE_DATA = &H800007D2
PDH_CSTATUS_ITEM_NOT_VALIDATED = &H800007D3
PDH_RETRY = &H800007D4
PDH_NO_DATA = &H800007D5
PDH_CALC_NEGATIVE_DENOMINATOR = &H800007D6
PDH_CALC_NEGATIVE_TIMEBASE = &H800007D7
PDH_CALC_NEGATIVE_VALUE = &H800007D8
PDH_DIALOG_CANCELLED = &H800007D9
PDH_CSTATUS_NO_OBJECT = &HC0000BB8
PDH_CSTATUS_NO_COUNTER = &HC0000BB9
PDH_CSTATUS_INVALID_DATA = &HC0000BBA
PDH_MEMORY_ALLOCATION_FAILURE = &HC0000BBB
PDH_INVALID_HANDLE = &HC0000BBC
PDH_INVALID_ARGUMENT = &HC0000BBD
PDH_FUNCTION_NOT_FOUND = &HC0000BBE
PDH_CSTATUS_NO_COUNTERNAME = &HC0000BBF
PDH_CSTATUS_BAD_COUNTERNAME = &HC0000BC0
PDH_INVALID_BUFFER = &HC0000BC1
PDH_INSUFFICIENT_BUFFER = &HC0000BC2
PDH_CANNOT_CONNECT_MACHINE = &HC0000BC3
PDH_INVALID_PATH = &HC0000BC4
PDH_INVALID_INSTANCE = &HC0000BC5
PDH_INVALID_DATA = &HC0000BC6
PDH_NO_DIALOG_DATA = &HC0000BC7
PDH_CANNOT_READ_NAME_STRINGS = &HC0000BC8
End Enum
Global Const ERROR_SUCCESS = 0
Declare Function PdhVbGetOneCounterPath _
Lib "PDH.DLL" _
(ByVal PathString As String, _
ByVal PathLength As Long, _
ByVal DetailLevel As Long, _
ByVal CaptionString As String) _
As Long
Declare Function PdhVbCreateCounterPathList _
Lib "PDH.DLL" _
(ByVal PERF_DETAIL As Long, _
ByVal CaptionString As String) _
As Long
Declare Function PdhVbGetCounterPathFromList _
Lib "PDH.DLL" _
(ByVal Index As Long, _
ByVal Buffer As String, _
ByVal BufferLength As Long) _
As Long
Declare Function PdhOpenQuery _
Lib "PDH.DLL" _
(ByVal Reserved As Long, _
ByVal dwUserData As Long, _
ByRef hQuery As Long) _
As PDH_STATUS
Declare Function PdhCloseQuery _
Lib "PDH.DLL" _
(ByVal hQuery As Long) _
As PDH_STATUS
Declare Function PdhVbAddCounter _
Lib "PDH.DLL" _
(ByVal QueryHandle As Long, _
ByVal CounterPath As String, _
ByRef CounterHandle As Long) _
As PDH_STATUS
Declare Function PdhCollectQueryData _
Lib "PDH.DLL" _
(ByVal QueryHandle As Long) _
As PDH_STATUS
Declare Function PdhVbIsGoodStatus _
Lib "PDH.DLL" _
(ByVal StatusValue As Long) _
As Long
Declare Function PdhVbGetDoubleCounterValue _
Lib "PDH.DLL" _
(ByVal CounterHandle As Long, _
ByRef CounterStatus As Long) _
As Double
Figure 4 PDH_VBDemo.frm
VERSION 5.00
Begin VB.Form Form1
Caption = "PDH_VBDemo - Matt Pietrek 1998, for MSJ"
ClientHeight = 2895
ClientLeft = 2445
ClientTop = 1515
ClientWidth = 6810
LinkTopic = "Form1"
ScaleHeight = 2895
ScaleWidth = 6810
Begin VB.OptionButton PerfDetail
Caption = "Wizard"
Height = 255
Index = 3
Left = 5400
TabIndex = 5
Top = 1080
Value = -1 'True
Width = 1215
End
Begin VB.OptionButton PerfDetail
Caption = "Expert"
Height = 255
Index = 2
Left = 5400
TabIndex = 4
Top = 840
Width = 1215
End
Begin VB.OptionButton PerfDetail
Caption = "Advanced"
Height = 255
Index = 1
Left = 5400
TabIndex = 3
Top = 600
Width = 1215
End
Begin VB.OptionButton PerfDetail
Caption = "Novice"
Height = 255
Index = 0
Left = 5400
TabIndex = 2
Top = 360
Width = 1215
End
Begin VB.Frame Frame1
Caption = "Detail Level"
Height = 1335
Left = 5280
TabIndex = 6
Top = 120
Width = 1455
End
Begin VB.CommandButton cmdAddCounter
Caption = "Add Counter..."
Height = 495
Left = 5280
TabIndex = 1
Top = 2280
Width = 1335
End
Begin VB.Timer Timer1
Enabled = 0 'False
Interval = 1000
Left = 120
Top = 2400
End
Begin VB.Label Label1
Height = 2535
Left = 120
TabIndex = 0
Top = 120
Width = 4935
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'--------------------------------------------------------------
' Matt Pietrek
' Microsoft Systems Journal, March 1998
' Program: PDH_VBDemo
' FILE: PDH_VBDemo.FRM
'--------------------------------------------------------------
Option Explicit
' Declare a structure to correlate a counter path to its
' associated handle values
Private Type CounterInfo
hCounter As Long
strName As String
End Type
Dim hQuery As Long
' Make room for 100 counters. Yeah, it probably should be a
' collection or something...
Dim Counters(0 To 99) As CounterInfo
' The array index where the next CounterInfo will be added
Dim currentCounterIdx As Long
' The current level of geeky counters to show in the
' PdhVbGetOneCounterPath dialog box
Dim iPerformanceDetail As PERF_DETAIL
'-------------------------------------------------------------
' Calls PdhVbAddCounter, then appends the counter path and
' handle to the Counters array.
'-------------------------------------------------------------
Public Sub AddCounter(strCounterName As String, hQuery As Long)
Dim pdhStatus As PDH_STATUS
Dim hCounter As Long
' Associate the counter path to the query
pdhStatus = PdhVbAddCounter(hQuery, strCounterName, hCounter)
' Append the path and handle to the Counters array
Counters(currentCounterIdx).hCounter = hCounter
Counters(currentCounterIdx).strName = strCounterName
' Bump up index to be ready for the next addition
currentCounterIdx = currentCounterIdx + 1
End Sub
'--------------------------------------------------------------
' Displays the counter names and values for each added counter.
' The display string is built by iterating through all of the
' added counters, and using CR-LF to split counter value
' out one to a line. The final result is dumped into a label
' (static text control.)
'--------------------------------------------------------------
Private Sub UpdateValues()
Dim dblCounterValue As Double
Dim pdhStatus As Long
Dim strInfo As String
Dim i As Long
' Get the most recent value for all the added counters
PdhCollectQueryData (hQuery)
' For each added counter...
For i = 0 To (currentCounterIdx - 1)
' Get the counter value as a double
dblCounterValue = _
PdhVbGetDoubleCounterValue(Counters(i).hCounter, pdhStatus)
' Verify that when we queried, the returned value was valid
If (pdhStatus = PDH_CSTATUS_VALID_DATA) _
Or (pdhStatus = PDH_CSTATUS_NEW_DATA) Then
' The counter value is valid, so append the counter path and
' its value onto the end of a string. Note the second argument
' to Format$, which ensures that fractional part of the number
' will be discarded. This is somewhat cheesy, but it's a lot
' more work to get something that's nicer in all cases.
strInfo = strInfo + Counters(i).strName + " = " + _
Format$(dblCounterValue, "0") + Chr$(13) + Chr$(10)
End If
Next i
Label1 = strInfo ' Blast the finished string into the text control
End Sub
Private Sub Form_Load()
Dim pdhStatus As PDH_STATUS
currentCounterIdx = 0 ' Not necesary, but C++ habits die hard
' Create the query, and verify that the request succeeded.
' Bail out if not.
pdhStatus = PdhOpenQuery(0, 1, hQuery)
If pdhStatus <> ERROR_SUCCESS Then
MsgBox "OpenQuery failed"
End
End If
' Add some interesting counters as defaults
AddCounter "\Process(_total)\Thread Count", hQuery
AddCounter "\Memory\Committed Bytes", hQuery
AddCounter "\Processor(0)\% Processor Time", hQuery
AddCounter "\System\Context Switches/Sec", hQuery
UpdateValues ' Force an immediate display of the counter values
PerfDetail_Click (3) ' Fake a click on the "Wizard" radio button
' Now that everything is set up, we can enable the 1 second timer.
' It's disabled up to this point.
Timer1.Enabled = True
End Sub
Private Sub Form_Unload(Cancel As Integer)
Timer1.Enabled = False ' Don't need periodic updates anymore
PdhCloseQuery (hQuery) ' Free the query
End Sub
Private Sub cmdAddCounter_Click()
Dim cbLen As Long
Dim strCounterPath As String * 256
Dim strCounterPath2 As String
' Display the dialog to pick one counter. strCounterPath is a buffer
' of 256 charaters
cbLen = PdhVbGetOneCounterPath(strCounterPath, 256, iPerformanceDetail, _
"MSJ PDH.DLL Demo - Matt Pietrek, 1998")
' If nothing was selected, bail out
If cbLen = 0 Then Exit Sub
' Make a string that contains only the valid characters that were written
' to by the call to PdhVbGetOneCounterPath
strCounterPath2 = Left$(strCounterPath, cbLen)
' Add the new counter to the query, and to the Counters array
AddCounter strCounterPath2, hQuery
UpdateValues ' Force an immediate display update
End Sub
Private Sub PerfDetail_Click(Index As Integer)
' Based upon the radio button that was pressed, set the
' iPerformanceDetail variable to the proper enum
Select Case Index
Case 0
iPerformanceDetail = PERF_DETAIL_NOVICE
Case 1
iPerformanceDetail = PERF_DETAIL_ADVANCED
Case 2
iPerformanceDetail = PERF_DETAIL_EXPERT
Case 3
iPerformanceDetail = PERF_DETAIL_WIZARD
End Select
End Sub
Private Sub Timer1_Timer()
' Set to trigger once a second. Update the counter display
UpdateValues
End Sub