Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 |

 

  Вопрос: Индикатор загрузки процессора Добавлено: 05.03.06 16:35  

Автор вопроса:  ekzarh | ICQ: 310698106 
Решил сделать индикатор загрузки процессора (в процентах).
Только даже не представляю с чего начать. Не нашел ни одной API функции для этого. Или не так искал? Знающие люди, помогите пожалуйста.

Ответить

  Ответы Всего ответов: 13  

Номер ответа: 1
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #1 Добавлено: 05.03.06 17:06
ZwQuerySystemInformation

Ответить

Номер ответа: 2
Автор ответа:
 Страшный Сон



Вопросов: 46
Ответов: 848
 Профиль | | #2 Добавлено: 05.03.06 22:34
Отвечать нужно поподробнее.

Этой функции в APIViewer'е нету. По всей видимости, она XPшная или Vist'овская, и в 98-й форточке работать не будет.

Ответить

Номер ответа: 3
Автор ответа:
 ekzarh



ICQ: 310698106 

Вопросов: 2
Ответов: 5
 Профиль | | #3 Добавлено: 05.03.06 23:28
ZwQuerySystemInformation
Этого нет ни в одном справочнике.
Не то что в APIViewer

Ответить

Номер ответа: 4
Автор ответа:
 SyavX



Вопросов: 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
    ;DefaultObject 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
    ;DefinitionLength As Long
    HeaderLength As Long
    ObjectNameTitleIndex As Long
    ObjectNameTitle As Long
    ObjectHelpTitleIndex As Long
    ObjectHelpTitle As Long
    ;DetailLevel As Long
    NumCounters As Long
    ;DefaultCounter 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
    ;DefaultScale As Long
    ;DetailLevel 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
Автор ответа:
 SyavX



Вопросов: 25
Ответов: 149
 Профиль | | #5 Добавлено: 06.03.06 00:05
Забыл написать - это класс

Ответить

Номер ответа: 6
Автор ответа:
 ekzarh



ICQ: 310698106 

Вопросов: 2
Ответов: 5
 Профиль | | #6 Добавлено: 06.03.06 00:59
Большое спасибо. Хотя я предполагал, что все будет несколько проще. Интересно, а покороче возможно? :-)
Да и вот еще что.

Описание в классе:

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


Вышеописанное - явная ошибка. Потому, что в форме следует

Private Sub Form_Unload(Cancel As Integer)
    CPU.ReleaseCPUData
    Set CPU = Nothing
End Sub

Соответственно ReleaseCPUData должно описываться, как функция. С поправкой работает прекрасно. Еще раз спасибо.

Ответить

Номер ответа: 7
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #7 Добавлено: 06.03.06 01:47
Интересно, сколько процентов покажет пример, если в реестре нет разделов HKEY_PERFORMANCE_DATA и HKEY_DYN_DATA ? Как например, у меня на ХР :)

P.S.
Не в тех справочниках искали ZwQuerySystemInformation. Описание в Windows NT 2000 Native API Reference

Ответить

Номер ответа: 8
Автор ответа:
 ekzarh



ICQ: 310698106 

Вопросов: 2
Ответов: 5
 Профиль | | #8 Добавлено: 06.03.06 13:16
Я может быть чего-то не понимаю, но у меня в XP SP2 все работает. А касаемо ZwQuerySystemInformation - ее даже в справочнике Эпплмана нет. А он, как бы, самый полный. Если не трудно, дайте ее описание пожалуйста.

Ответить

Номер ответа: 9
Автор ответа:
 HOOLIGAN



Вопросов: 0
Ответов: 1066
 Профиль | | #9 Добавлено: 06.03.06 14:14
Ну если тебе только на своем компе чтобы работало, то хватит и этого примера.

Описание тут:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/zwquerysysteminformation.asp

А справочник эплмана самый бедный из тех, что я видел :) (после api-guide'а)

Ответить

Номер ответа: 10
Автор ответа:
 ekzarh



ICQ: 310698106 

Вопросов: 2
Ответов: 5
 Профиль | | #10 Добавлено: 06.03.06 14:50
На самом деле мне, конечно, надо что бы это работало на любой тачке. Вся песня в том, что именно мне это как раз и не надо. Делаю я это для человека, который боится, что у него камушек на ноутбуке вылетит от перегруза (и перегрева соответственно). Что бы успокоился. А вот у него под Home Edition машинка крутится. Не знаю, как там заработает. Вероятно только опытным путем проверить остается.
За ссылку спасибо. Только не поможет она мне ничем. В программировании с использованием API я новичок, потому путанные объяснения от майкрософт все равно, что китайская грамота.
Тем более, что там никак не описано ее объявление в VB.
А в APIViewer ее нет, как уже было сказано выше. Где хоть искать этот Windows NT 2000 Native API Reference?
Беда с этими API. Особенно, когда не знаешь с какого конца подходить к ним.

Ответить

Номер ответа: 11
Автор ответа:
 [root]



Вопросов: 45
Ответов: 1212
 Web-сайт: bit.pirit.info
 Профиль | | #11
Добавлено: 06.03.06 15:48
Есть такая прога Kerish Anti Spy(исходник).
И она помимо всего показывает загруженность процессора.
По моему есть на сайте, если хочешь брошу на мыло?

Ответить

Номер ответа: 12
Автор ответа:
 ekzarh



ICQ: 310698106 

Вопросов: 2
Ответов: 5
 Профиль | | #12 Добавлено: 06.03.06 16:32
Было бы здорово.

Ответить

Номер ответа: 13
Автор ответа:
 [root]



Вопросов: 45
Ответов: 1212
 Web-сайт: bit.pirit.info
 Профиль | | #13
Добавлено: 06.03.06 16:51
лови, бросил на мыло

Ответить

Страница: 1 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам