Замер степени использования процессора
Недавно
в статье, посвящённой недокументированным возможностям Windows, я обнаружил
интересный способ измерения степени использования процессора. Дело в том, что в
Windows 9x существуют счётчики Performance Counters, которые можно включить из
реестра, и в реестр же они будут посылать результаты замеров. Например
загруженности процессора. Есть они и в NT, но доступ к ним сложнее.
К
моему собственному удивлению результат перевода С на человеческий VB отлично
заработал! По-сему, если Вашей программе нужно знать загруженность проца, или
если Вы заинтересуетесь доступом в реестр из WinApi32, то Вы можете
познакомиться с простеньким примером. Разумеется в полном варианте нужно было
бы вставить проверку типа Windows (например через GetWindowsVersion),
сворачивание в SysTray и т.п., но в "укороченном" виде Вам будет
проще приспособить данную фичу Windows к своим потребностям.
Итак.
Если у Вас не NT. Расположите на форме кнопочку. Назовём её cmdStart. Как
водится, в раздел General Declarations вставляем:
Открыть
нужный ключ:
Private Declare Function
RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" ( _
ByVal hkey As Long, _
ByVal pSubKey As String, _
ByVal ulOptions As Long, _
ByVal samDesired As Long, _
phkResult As Long) As Long
hkey, lpSubKey - пути к
ключу,
ulOptions
- зарезервировано: должно быть ноль,
samDesired
- тип доступа: комбинация предопределённых констант,
phkResult
- переменная, получающая хэндл нужного ключа. Не забудьте потом закрыть.
Получить
тип и значение параметра из ранее открытого ключа:
Private Declare Function
RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA"
( _
ByVal hkey As Long, _
ByVal lpValueName As String, _
ByVal lpReserved As Long, _
lpType As Long, _
lpData As Any, _
lpcbData As Long) As Long
hkey
- хэндл открытого ранее ключа,
lpValueName
- имя параметра, который нужно прочитать,
lpReserved
- зарезервировано: должно быть ноль,
lpType
- переменная, в которую будет возвращаться тип параметра
можно
передать ноль, если тип не требуется (нам, кстати, передаст 3 - REG_BINARY),
lpData
- то, что нас интересует,
lpcbData
- переменная, которая содержит длину буфера под lpData,
после
выполнения будет содержать кол-во в действительности переданных байт
у
нас - длина слова: 4. Если переменную заменить просто на 4 - тоже работает
Закрытие ранее открытого ключа:
Private Declare Function RegCloseKey
Lib "advapi32.dll" (ByVal hkey As Long) As Long
Некоторые
константы из API Viewer:
Private Const HKEY_DYN_DATA =
&H80000006
Private Const STANDARD_RIGHTS_ALL =
&H1F0000
Private Const READ_CONTROL =
&H20000
Private Const STANDARD_RIGHTS_READ =
(READ_CONTROL)
Private Const KEY_QUERY_VALUE =
&H1
Private Const KEY_SET_VALUE =
&H2
Private Const KEY_CREATE_SUB_KEY =
&H4
Private Const KEY_ENUMERATE_SUB_KEYS
= &H8
Private Const KEY_NOTIFY = &H10
Private Const KEY_CREATE_LINK =
&H20
Private Const SYNCHRONIZE =
&H100000
Private Const KEY_ALL_ACCESS =
((STANDARD_RIGHTS_ALL OR _
KEY_QUERY_VALUE OR KEY_SET_VALUE OR
_
KEY_CREATE_SUB_KEY Or
KEY_ENUMERATE_SUB_KEYS Or _
KEY_NOTIFY Or KEY_CREATE_LINK) And
(Not SYNCHRONIZE))
Private Const KEY_READ =
((STANDARD_RIGHTS_READ Or _
KEY_QUERY_VALUE Or
KEY_ENUMERATE_SUB_KEYS Or _
KEY_NOTIFY) And (Not SYNCHRONIZE))
Для
служебных нужд:
Самый
ресурсощедящий способ выждать паузу (в миллисекундах):
Private Declare Sub Sleep Lib
"kernel32" (ByVal dwMilliseconds As Long)
Всегда пригодится:
Private Declare Function
SetWindowPos Lib "user32" (ByVal hwnd As Long, _
ByVal hWndInsertAfter As Long, _
ByVal x As Long, _
ByVal y As Long, _
ByVal cx As Long, _
ByVal cy As Long, _
ByVal WFlags As Long) As Long
А это
наше:
Dim hkey As Long
Dim dwCPUUsage As Long
Dim lpcbData As Longпо-моему действительно лучше
выкинуть,
подставив
в нужных местах 4. Ау, теоретики!
Dim bStart As Boolean
Private Sub Form_Load()
SetWindowPos Me.hwnd, -1, 0, 0, 0,
0, 3
видим всегда
End Sub
Private Sub cmdStart_Click()
bStart = Not bStart
bStart
- это Вкл-Выкл. См. далее
If bStart Then
если - True - начинаем
cmdStart.Caption
= "&Stop"
меняем
название кнопочки
Включаем
счётчик, считывая значение соответствующего ключа:
If RegOpenKeyEx(HKEY_DYN_DATA,
"PerfStatsStartStat", 0, KEY_ALL_ACCESS, _
hkey) 0 Then Exit Sub
lpcbData = 4
RegQueryValueEx hkey,
"KERNELCPUUsage", 0, 0, dwCPUUsage, lpcbData
RegCloseKey
hkey
закрыть
ключ
Считываем
значение прямо из реестра:
If RegOpenKeyEx(HKEY_DYN_DATA,
"PerfStatsStatData", 0, KEY_READ, _
hkey) 0 Then Exit Sub
Do While bStart
пока
ещё раз не нажмём на кнопочку