Страница: 1 |
Вопрос: Индикатор загрузки процессора | Добавлено: 05.03.06 16:35 |
Автор вопроса: ![]() |
Решил сделать индикатор загрузки процессора (в процентах).
Только даже не представляю с чего начать. Не нашел ни одной API функции для этого. Или не так искал? Знающие люди, помогите пожалуйста. |
Ответы | Всего ответов: 13 |
Номер ответа: 1 Автор ответа: ![]() ![]() Вопросов: 0 Ответов: 1066 |
Профиль | Цитата | #1 | Добавлено: 05.03.06 17:06 |
ZwQuerySystemInformation |
Номер ответа: 2 Автор ответа: ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Вопросов: 46 Ответов: 848 |
Профиль | Цитата | #2 | Добавлено: 05.03.06 22:34 |
Отвечать нужно поподробнее.
Этой функции в APIViewer'е нету. По всей видимости, она XPшная или Vist'овская, и в 98-й форточке работать не будет. |
Номер ответа: 3 Автор ответа: ![]() ![]() ![]() ![]() ![]() ![]() ICQ: 310698106 Вопросов: 2 Ответов: 5 |
Профиль | Цитата | #3 | Добавлено: 05.03.06 23:28 |
ZwQuerySystemInformation
Этого нет ни в одном справочнике. Не то что в APIViewer |
Номер ответа: 4 Автор ответа: ![]() ![]() ![]() Вопросов: 25 Ответов: 149 |
Профиль | Цитата | #4 | Добавлено: 06.03.06 00:03 |
Option Explicit
'I got the Idea from the program BiCPU http://www.nospaceleft.com. 'I ported most of my source from: 'adCpuUsage http://www.aldyn.ru Private Const ClassName As String = "CPULoad" Private Const Err_Initialize As Long = vbObjectError + 8001 Private Const Err_UnableToStartPerfmon As Long = vbObjectError + 8002 Private Const Err_CPUIndexOOB As Long = vbObjectError + 8003 Private Const Err_CantFindProcessorPerfMon As Long = vbObjectError + 8004 Private Const Err_CantFindCPUUsagePerfMon As Long = vbObjectError + 8005 Private Const Err_UnableToReadPDB As Long = vbObjectError + 8006 Private Declare Sub Memcopy Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal dwLength As Long) Private Declare Function SystemTimeToFileTime Lib "kernel32" (lpSystemTime As SystemTime, lpFileTime As Currency) As Long Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long 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 Private Declare Sub GetSystemInfo Lib "kernel32" (lpSystemInfo As SYSTEM_INFO) Private Type SYSTEM_INFO dwOemID As Long dwPageSize As Long lpMinimumApplicationAddress As Long lpMaximumApplicationAddress As Long dwActiveProcessorMask As Long dwNumberOrfProcessors As Long dwProcessorType As Long dwAllocationGranularity As Long dwReserved As Long End Type Private Const HKEY_DYN_DATA = &H80000006 Private Const HKEY_PERFORMANCE_DATA = &H80000004 Private Const REG_DWORD = 4 Private Const ERROR_SUCCESS = 0& Private Const ERROR_MORE_DATA = 234 Private Type OSVERSIONINFO dwOSVersionInfoSize As Long dwMajorVersion As Long dwMinorVersion As Long dwBuildNumber As Long dwPlatformId As Long szCSDVersion As String * 128 ' Maintenance string for PSS usage End Type Private Const VER_PLATFORM_WIN32_NT = 2 Private Const VER_PLATFORM_WIN32_WINDOWS = 1 Private Const VER_PLATFORM_WIN32s = 0 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 STANDARD_RIGHTS_ALL = &H1F0000 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 Type FILETIME dwLowDateTime As Long dwHighDateTime As Long End Type Private Type SystemTime wYear As Integer wMonth As Integer wDayOfWeek As Integer wDay As Integer wHour As Integer wMinute As Integer wSecond As Integer wMilliseconds As Integer End Type Private Type LARGE_INTEGER lowpart As Long highpart As Long End Type Private Type PERF_INSTANCE_DEFINITION ByteLength As Long ParentObjectTitleIndex As Long ParentObjectInstance As Long UniqueID As Long NameOffset As Long NameLength As Long End Type Private Type PERF_COUNTER_BLOCK ByteLength As Long End Type Private Type PERF_DATA_BLOCK Signature As String * 4 LittleEndian As Long Version As Long Revision As Long TotalByteLength As Long HeaderLength As Long NumObjectTypes As Long ![]() SystemTime As SystemTime PerfTime As LARGE_INTEGER PerfFreq As LARGE_INTEGER PerTime100nSec As LARGE_INTEGER SystemNameLength As Long SystemNameOffset As Long End Type Private Type PERF_OBJECT_TYPE TotalByteLength As Long ![]() HeaderLength As Long ObjectNameTitleIndex As Long ObjectNameTitle As Long ObjectHelpTitleIndex As Long ObjectHelpTitle As Long ![]() NumCounters As Long ![]() NumInstances As Long CodePage As Long PerfTime As LARGE_INTEGER PerfFreq As LARGE_INTEGER End Type Private Type PERF_COUNTER_DEFINITION ByteLength As Long CounterNameTitleIndex As Long CounterNameTitle As Long CounterHelpTitleIndex As Long CounterHelpTitle As Long ![]() ![]() CounterType As Long CounterSize As Long CounterOffset As Long End Type Private Const Processor_IDX_Str As String = "238" Private Const Processor_IDX As Long = 238 Private Const CPUUsageIDX As Long = 6 Private m_lProcessorsCount As Long Private m_lBufferSize As Long Private m_bIsWinNT As Boolean Private m_bW9xCollecting As Boolean Private m_lW9xCpuUsage As Long Private m_hW9xCpuKey As Long Private PDB As PERF_DATA_BLOCK Private POT As PERF_OBJECT_TYPE Private PCD As PERF_COUNTER_DEFINITION Private PID As PERF_INSTANCE_DEFINITION Private PCB As PERF_COUNTER_BLOCK Private VI As OSVERSIONINFO Private SysTime As Currency Private PrevSysTime As Currency Private m_aCounters() As Currency Private m_aPrevCounters() As Currency Private Const ByteIncrement As Long = 4096 Private Sub Class_Initialize() VI.dwOSVersionInfoSize = Len(VI) If GetVersionEx(VI) = 0 Then Err.Raise Err_Initialize, ClassName & ".Initialize", "Невозможно определить версию Windows" End If m_bIsWinNT = (VI.dwPlatformId = VER_PLATFORM_WIN32_NT) m_lProcessorsCount = -1 m_lBufferSize = ByteIncrement End Sub Private Sub Class_Terminate() ReleaseCPUData End Sub Public Function CollectCPUData() As Boolean Dim H As Long, R As Long Dim aBuf() As Byte, lAllocSz As Long Dim lSrc As Long, lDest As Long Dim ptrPOT As Long, ptrPCB As Long Dim i As Long, lCPU As Long Dim ST As Currency Dim sInstanceName As String If m_bIsWinNT = True Then 'Если система - NT 'Allocate the buffer. lAllocSz = m_lBufferSize 'Initial allocation size ReDim aBuf(1 To lAllocSz) As Byte 'We loop until RQVex says that our buffer is large enough While RegQueryValueEx(HKEY_PERFORMANCE_DATA, Processor_IDX_Str, 0&, 0&, aBuf(1), m_lBufferSize) = ERROR_MORE_DATA lAllocSz = lAllocSz + ByteIncrement 'Get a Buffer that is big enough. Increment the allocation size ReDim aBuf(1 To lAllocSz) As Byte m_lBufferSize = lAllocSz 'Tell RQVex how big we allocated the buffer Wend lDest = VarPtr(PDB) lSrc = VarPtr(aBuf(1)) Memcopy ByVal lDest, ByVal lSrc, LenB(PDB) 'Because RegQueryValueEx modifies the Data in BufferSize, reset it to the Proper value for the buffer size 'We want to save the size so that next time we hopefully wont have to loop so much to find the size needed m_lBufferSize = lAllocSz 'Проверка If PDB.Signature <> "PERF" Then Err.Raise Err_UnableToReadPDB, ClassName & ".CollectCPUData()", "Невозможно считать значения загрузки процессора" 'Locate the performance object lDest = VarPtr(POT) lSrc = VarPtr(aBuf(1)) + PDB.HeaderLength For i = 1 To PDB.NumObjectTypes Memcopy ByVal lDest, ByVal lSrc, LenB(POT) ptrPOT = lSrc If POT.ObjectNameTitleIndex = Processor_IDX Then Exit For lSrc = lSrc + POT.TotalByteLength Next i 'Проверка If POT.ObjectNameTitleIndex <> Processor_IDX Then Err.Raise Err_CantFindProcessorPerfMon, ClassName & ".CollectData", "Невозможно найти объект загрузки 'Processor'" 'Получение количества процессоров If m_lProcessorsCount < 1 Then m_lProcessorsCount = GetCPUCount() 'Locate the "% CPU usage" counter definition lDest = VarPtr(PCD) lSrc = lSrc + POT.HeaderLength For i = 1 To POT.NumCounters Memcopy ByVal lDest, ByVal lSrc, LenB(PCD) If PCD.CounterNameTitleIndex = CPUUsageIDX Then Exit For lSrc = lSrc + PCD.ByteLength Next i 'Проверка If PCD.CounterNameTitleIndex <> CPUUsageIDX Then Err.Raise Err_CantFindCPUUsagePerfMon, ClassName & ".CollectData", "Невозможно найти счетчик загрузки процессора '% CPU usage'" 'Collecting counters lSrc = ptrPOT + POT.DefinitionLength For i = 1 To POT.NumInstances lDest = VarPtr(PID) Memcopy ByVal lDest, ByVal lSrc, LenB(PID) 'Get the Instance name. The "-2" is because we dont need the terminating double null sInstanceName = Space(PID.NameLength - 2) Memcopy ByVal sInstanceName, ByVal lSrc + PID.NameOffset, PID.NameLength - 2 sInstanceName = StrConv(sInstanceName, vbFromUnicode) lSrc = lSrc + PID.ByteLength lDest = VarPtr(PCB) Memcopy ByVal lDest, ByVal lSrc, LenB(PCB) ptrPCB = lSrc 'Win2K has an instance for the '% CPU usage' named '_Total' we dont want to report on that instance, we want the actual processor 'The processor instances are named 0,1,2, etc... If IsNumeric(sInstanceName) Then 'Assumption.. the instance name will be an integer for the cpu index ie "0" = 0 = first cpu lCPU = CLng(sInstanceName) m_aPrevCounters(lCPU) = m_aCounters(lCPU) Memcopy ByVal VarPtr(m_aCounters(lCPU)), ByVal ptrPCB + PCD.CounterOffset, LenB(m_aCounters(lCPU)) End If lSrc = lSrc + PCB.ByteLength Next i PrevSysTime = SysTime SystemTimeToFileTime PDB.SystemTime, ST SysTime = ST Else 'Для Win9x If Not m_bW9xCollecting Then If Not RegOpenKeyEx(HKEY_DYN_DATA, "PerfStats\StartStat", 0&, KEY_ALL_ACCESS, H) = ERROR_SUCCESS Then Err.Raise Err_UnableToStartPerfmon, ClassName & ".CollectCPRData()", "Невозможно запустить мониторинг" End If Call RegQueryValueEx(H, "KERNEL\CPUUsage", 0&, REG_DWORD, m_lW9xCpuUsage, LenB(m_lW9xCpuUsage)) Call RegCloseKey(H) If Not RegOpenKeyEx(HKEY_DYN_DATA, "PerfStats\StatData", 0&, KEY_READ, m_hW9xCpuKey) = ERROR_SUCCESS Then Err.Raise Err_UnableToReadPDB, ClassName & ".CollectCPUData()", "Невозможно прочитать значения мониторинга" End If m_bW9xCollecting = True End If Call RegQueryValueEx(m_hW9xCpuKey, "KERNEL\CPUUsage", 0&, REG_DWORD, m_lW9xCpuUsage, LenB(m_lW9xCpuUsage)) End If End Function Public Function GetCPUCount() As Long Dim SI As SYSTEM_INFO If m_lProcessorsCount < 1 Then GetSystemInfo SI GetCPUCount = SI.dwNumberOrfProcessors m_lProcessorsCount = SI.dwNumberOrfProcessors 'Zero based array ReDim m_aPrevCounters(0 To m_lProcessorsCount - 1) As Currency ReDim m_aCounters(0 To m_lProcessorsCount - 1) As Currency Else GetCPUCount = m_lProcessorsCount End If End Function Public Function GetCPUUsage(Optional ByVal CPU_Index As Long = 1) As Long 'NOTE*** Our Counter Arrays are 0 Based, but what is passed is 1 based.. 'Function Returns 0 to 100 'deincrement for our internal array CPU_Index = CPU_Index - 1 If m_bIsWinNT Then If m_lProcessorsCount < 0 Then CollectCPUData If (CPU_Index >= m_lProcessorsCount) Or (CPU_Index < 0) Then Err.Raise Err_CPUIndexOOB, ClassName & ".GetCPUUsage()", "Номер процессора выходит за границы" If PrevSysTime = SysTime Then GetCPUUsage = 0 Else GetCPUUsage = CLng(100 * (1 - (m_aCounters(CPU_Index) - m_aPrevCounters(CPU_Index)) / (SysTime - PrevSysTime))) End If Else If Not CPU_Index = 0 Then Err.Raise Err_CPUIndexOOB, ClassName & ".GetCPUUsage()", "Номер процессора выходит за границы" If Not m_bW9xCollecting Then CollectCPUData GetCPUUsage = m_lW9xCpuUsage End If End Function Private Sub ReleaseCPUData() Dim H As Long If m_bIsWinNT Then Exit Sub If Not m_bW9xCollecting Then Exit Sub m_bW9xCollecting = False Call RegCloseKey(m_hW9xCpuKey) m_hW9xCpuKey = 0 If Not RegOpenKeyEx(HKEY_DYN_DATA, "PerfStats\StopStat", 0, KEY_ALL_ACCESS, H) = ERROR_SUCCESS Then Exit Sub Call RegQueryValueEx(H, "KERNEL\CPUUsage", 0&, REG_DWORD, m_lW9xCpuUsage, LenB(m_lW9xCpuUsage)) Call RegCloseKey(H) End Sub '# How to use: 'Dim CPU As CPULoad 'Private Sub Form_Load() ' Set CPU = New CPULoad 'End Sub 'Private Sub tmrCPU_Timer() ' CPU.CollectCPUData ' Me.Cls ' Me.Print CPU.GetCPUUsage 'End Sub 'Private Sub Form_Unload(Cancel As Integer) ' CPU.ReleaseCPUData ' Set CPU = Nothing 'End Sub |
Номер ответа: 5 Автор ответа: ![]() ![]() ![]() Вопросов: 25 Ответов: 149 |
Профиль | Цитата | #5 | Добавлено: 06.03.06 00:05 |
Забыл написать - это класс |
Номер ответа: 6 Автор ответа: ![]() ![]() ![]() ![]() ![]() ![]() ICQ: 310698106 Вопросов: 2 Ответов: 5 |
Профиль | Цитата | #6 | Добавлено: 06.03.06 00:59 |
Большое спасибо. Хотя я предполагал, что все будет несколько проще. Интересно, а покороче возможно? ![]() Да и вот еще что. Описание в классе: Private Sub ReleaseCPUData() ![]() If m_bIsWinNT Then Exit Sub If Not m_bW9xCollecting Then Exit Sub m_bW9xCollecting = False Call RegCloseKey(m_hW9xCpuKey) m_hW9xCpuKey = 0 If Not RegOpenKeyEx(HKEY_DYN_DATA, "PerfStats\StopStat", 0, KEY_ALL_ACCESS, H) = ERROR_SUCCESS Then Exit Sub Call RegQueryValueEx(H, "KERNEL\CPUUsage", 0&, REG_DWORD, m_lW9xCpuUsage, LenB(m_lW9xCpuUsage)) Call RegCloseKey(H) End Sub Вышеописанное - явная ошибка. Потому, что в форме следует Private Sub Form_Unload(Cancel As Integer) CPU.ReleaseCPUData Set CPU = Nothing End Sub Соответственно ReleaseCPUData должно описываться, как функция. С поправкой работает прекрасно. Еще раз спасибо. |
Номер ответа: 7 Автор ответа: ![]() ![]() Вопросов: 0 Ответов: 1066 |
Профиль | Цитата | #7 | Добавлено: 06.03.06 01:47 |
Интересно, сколько процентов покажет пример, если в реестре нет разделов HKEY_PERFORMANCE_DATA и HKEY_DYN_DATA ? Как например, у меня на ХР ![]() P.S. Не в тех справочниках искали ZwQuerySystemInformation. Описание в Windows NT 2000 Native API Reference |
Номер ответа: 8 Автор ответа: ![]() ![]() ![]() ![]() ![]() ![]() ICQ: 310698106 Вопросов: 2 Ответов: 5 |
Профиль | Цитата | #8 | Добавлено: 06.03.06 13:16 |
Я может быть чего-то не понимаю, но у меня в XP SP2 все работает. А касаемо ZwQuerySystemInformation - ее даже в справочнике Эпплмана нет. А он, как бы, самый полный. Если не трудно, дайте ее описание пожалуйста. |
Номер ответа: 9 Автор ответа: ![]() ![]() Вопросов: 0 Ответов: 1066 |
Профиль | Цитата | #9 | Добавлено: 06.03.06 14:14 |
Ну если тебе только на своем компе чтобы работало, то хватит и этого примера.
Описание тут: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/zwquerysysteminformation.asp А справочник эплмана самый бедный из тех, что я видел ![]() |
Номер ответа: 10 Автор ответа: ![]() ![]() ![]() ![]() ![]() ![]() ICQ: 310698106 Вопросов: 2 Ответов: 5 |
Профиль | Цитата | #10 | Добавлено: 06.03.06 14:50 |
На самом деле мне, конечно, надо что бы это работало на любой тачке. Вся песня в том, что именно мне это как раз и не надо. Делаю я это для человека, который боится, что у него камушек на ноутбуке вылетит от перегруза (и перегрева соответственно). Что бы успокоился. А вот у него под Home Edition машинка крутится. Не знаю, как там заработает. Вероятно только опытным путем проверить остается.
За ссылку спасибо. Только не поможет она мне ничем. В программировании с использованием API я новичок, потому путанные объяснения от майкрософт все равно, что китайская грамота. Тем более, что там никак не описано ее объявление в VB. А в APIViewer ее нет, как уже было сказано выше. Где хоть искать этот Windows NT 2000 Native API Reference? Беда с этими API. Особенно, когда не знаешь с какого конца подходить к ним. |
Номер ответа: 11 Автор ответа: ![]() ![]() Вопросов: 45 Ответов: 1212 |
Web-сайт: Профиль | Цитата | #11 | Добавлено: 06.03.06 15:48 |
Есть такая прога Kerish Anti Spy(исходник).
И она помимо всего показывает загруженность процессора. По моему есть на сайте, если хочешь брошу на мыло? |
Номер ответа: 12 Автор ответа: ![]() ![]() ![]() ![]() ![]() ![]() ICQ: 310698106 Вопросов: 2 Ответов: 5 |
Профиль | Цитата | #12 | Добавлено: 06.03.06 16:32 |
Было бы здорово. |
Номер ответа: 13 Автор ответа: ![]() ![]() Вопросов: 45 Ответов: 1212 |
Web-сайт: Профиль | Цитата | #13 | Добавлено: 06.03.06 16:51 |
лови, бросил на мыло
|
Страница: 1 |
|