.net 要获取CPU和内存的使用率,一般是通过 PerformanceCounter 或者 WMI 查询得到,但是如果操作系统经常不正常断电或者别的什么原因,让系统的性能计数器抽风了,可能就会造成初始化 PerformanceCounter 对象出错。

性能计数器错误一般可以通过 lodctr /r 可以修复,但是时不时要这么搞一下,对用户总是太不友好了,所以能通过 Win32API 来获取也是一个不错的选项。

代码已封装到两个工具类 CpuUsageNt 和 MemUsage 里面了

''' <summary>
''' Inherits the CPUUsage class and implements the Query method for Windows NT systems.
''' </summary>
''' <remarks>
''' <p>This class works on Windows NT4, Windows 2000, Windows XP, Windows .NET Server and higher.</p>
''' </remarks>
Private NotInheritable Class CpuUsageNt
    ''' <summary>
    ''' Initializes a new CpuUsageNt instance.
    ''' </summary>
    ''' <exception cref="NotSupportedException">One of the system calls fails.</exception>
    Public Sub New()
        Dim timeInfo(31) As Byte ' SYSTEM_TIME_INFORMATION structure
        Dim perfInfo(311) As Byte ' SYSTEM_PERFORMANCE_INFORMATION structure
        Dim baseInfo(43) As Byte ' SYSTEM_BASIC_INFORMATION structure
        Dim ret As Integer

        If (Environment.OSVersion.Platform <> PlatformID.Win32NT) Then
            Throw New NotSupportedException()
        End If

        ' get new system time
        ret = NtQuerySystemInformation(SYSTEM_TIMEINFORMATION, timeInfo, timeInfo.Length, IntPtr.Zero)
        If ret <> NO_ERROR Then
            Throw New NotSupportedException()
        End If
        ' get new CPU's idle time
        ret = NtQuerySystemInformation(SYSTEM_PERFORMANCEINFORMATION, perfInfo, perfInfo.Length, IntPtr.Zero)
        If ret <> NO_ERROR Then
            Throw New NotSupportedException()
        End If
        ' get number of processors in the system
        ret = NtQuerySystemInformation(SYSTEM_BASICINFORMATION, baseInfo, baseInfo.Length, IntPtr.Zero)
        If ret <> NO_ERROR Then
            Throw New NotSupportedException()
        End If
        ' store new CPU's idle and system time and number of processors
        _oldIdleTime = BitConverter.ToInt64(perfInfo, 0) ' SYSTEM_PERFORMANCE_INFORMATION.liIdleTime
        _oldSystemTime = BitConverter.ToInt64(timeInfo, 8) ' SYSTEM_TIME_INFORMATION.liKeSystemTime
        _processorCount = baseInfo(40)
    End Sub

    ''' <summary>
    ''' Determines the current average CPU load.
    ''' </summary>
    ''' <returns>An integer that holds the CPU load percentage.</returns>
    ''' <exception cref="NotSupportedException">One of the system calls fails. The CPU time can not be obtained.</exception>
    Public Function Query() As Integer
        Dim timeInfo(31) As Byte ' SYSTEM_TIME_INFORMATION structure
        Dim perfInfo(311) As Byte ' SYSTEM_PERFORMANCE_INFORMATION structure

        ' get new system time
        Dim ret As Integer = NtQuerySystemInformation(SYSTEM_TIMEINFORMATION, timeInfo, timeInfo.Length, IntPtr.Zero)
        If ret <> NO_ERROR Then
            Throw New NotSupportedException()
        End If
        ' get new CPU's idle time
        ret = NtQuerySystemInformation(SYSTEM_PERFORMANCEINFORMATION, perfInfo, perfInfo.Length, IntPtr.Zero)
        If ret <> NO_ERROR Then
            Throw New NotSupportedException()
        End If
        ' CurrentValue = NewValue - OldValue
        Dim dbIdleTime As Double = BitConverter.ToInt64(perfInfo, 0) - _oldIdleTime
        Dim dbSystemTime As Double = BitConverter.ToInt64(timeInfo, 8) - _oldSystemTime
        ' CurrentCpuIdle = IdleTime / SystemTime
        If dbSystemTime <> 0 Then
            dbIdleTime = dbIdleTime / dbSystemTime
        End If
        ' CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors
        dbIdleTime = 100.0 - dbIdleTime * 100.0 / _processorCount + 0.5
        ' store new CPU's idle and system time
        _oldIdleTime = BitConverter.ToInt64(perfInfo, 0) ' SYSTEM_PERFORMANCE_INFORMATION.liIdleTime
        _oldSystemTime = BitConverter.ToInt64(timeInfo, 8) ' SYSTEM_TIME_INFORMATION.liKeSystemTime
        Return CInt(Fix(dbIdleTime))
    End Function

    ''' <summary>
    ''' NtQuerySystemInformation is an internal Windows function that retrieves various kinds of system information.
    ''' </summary>
    ''' <param name="dwInfoType">One of the values enumerated in SYSTEM_INFORMATION_CLASS, indicating the kind of system information to be retrieved.</param>
    ''' <param name="lpStructure">Points to a buffer where the requested information is to be returned. The size and structure of this information varies depending on the value of the SystemInformationClass parameter.</param>
    ''' <param name="dwSize">Length of the buffer pointed to by the SystemInformation parameter.</param>
    ''' <param name="returnLength">Optional pointer to a location where the function writes the actual size of the information requested.</param>
    ''' <returns>Returns a success NTSTATUS if successful, and an NTSTATUS error code otherwise.</returns>
    <DllImport("ntdll", EntryPoint:="NtQuerySystemInformation")>
    Private Shared Function NtQuerySystemInformation(ByVal dwInfoType As Integer,
                                                     ByVal lpStructure() As Byte,
                                                     ByVal dwSize As Integer,
                                                     ByVal returnLength As IntPtr) As Integer
    End Function

    ''' <summary>Returns the number of processors in the system in a SYSTEM_BASIC_INFORMATION structure.</summary>
    Private Const SYSTEM_BASICINFORMATION As Integer = 0
    ''' <summary>Returns an opaque SYSTEM_PERFORMANCE_INFORMATION structure.</summary>
    Private Const SYSTEM_PERFORMANCEINFORMATION As Integer = 2
    ''' <summary>Returns an opaque SYSTEM_TIMEOFDAY_INFORMATION structure.</summary>
    Private Const SYSTEM_TIMEINFORMATION As Integer = 3
    ''' <summary>The value returned by NtQuerySystemInformation is no error occurred.</summary>
    Private Const NO_ERROR As Integer = 0
    ''' <summary>Holds the old idle time.</summary>
    Private _oldIdleTime As Long
    ''' <summary>Holds the old system time.</summary>
    Private _oldSystemTime As Long
    ''' <summary>Holds the number of processors in the system.</summary>
    Private _processorCount As Double
End Class
CpuUsageNt

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-11-23
  • 2021-12-13
  • 2021-07-29
  • 2022-12-23
  • 2021-12-18
猜你喜欢
  • 2021-08-09
  • 2021-12-18
  • 2021-11-23
  • 2021-12-18
  • 2021-12-18
相关资源
相似解决方案