• VB.NET 在 Windows下通过WIn32API获取CPU和内存的使用率


    .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
     1 Private NotInheritable Class MemUsage
     2     <StructLayout(LayoutKind.Sequential)>
     3     Private Structure MEMORY_INFO
     4         ''' <summary>
     5         ''' 当前结构体大小
     6         ''' </summary>
     7         Public dwLength As UInteger
     8         ''' <summary>
     9         ''' 当前内存使用率
    10         ''' </summary>
    11         Public dwMemoryLoad As UInteger
    12         ''' <summary>
    13         ''' 总计物理内存大小
    14         ''' </summary>
    15         Public dwTotalPhys As UInteger
    16         ''' <summary>
    17         ''' 可用物理内存大小
    18         ''' </summary>
    19         Public dwAvailPhys As UInteger
    20         ''' <summary>
    21         ''' 总计交换文件大小
    22         ''' </summary>
    23         Public dwTotalPageFile As UInteger
    24         ''' <summary>
    25         ''' 可用交换文件大小
    26         ''' </summary>
    27         Public dwAvailPageFile As UInteger
    28         ''' <summary>
    29         ''' 总计虚拟内存大小
    30         ''' </summary>
    31         Public dwTotalVirtual As UInteger
    32         ''' <summary>
    33         ''' 可用虚拟内存大小
    34         ''' </summary>
    35         Public dwAvailVirtual As UInteger
    36     End Structure
    37     <DllImport("kernel32")>
    38     Private Shared Sub GlobalMemoryStatus(ByRef meminfo As MEMORY_INFO)
    39     End Sub
    40 
    41     Public Function Query() As Int32
    42         Dim iRet As Int32 = 0
    43         Try
    44             Dim MemInfo As New MEMORY_INFO
    45             GlobalMemoryStatus(MemInfo)
    46             iRet = CInt(MemInfo.dwMemoryLoad)
    47             Debug.Print("[DEBUG] GlobalMemoryStatus dwMemoryLoad={0}", iRet)
    48         Catch ex As Exception
    49             Debug.Print("[WARN ] GlobalMemoryStatus Err:{0}", ex.Message)
    50         End Try
    51         Return iRet
    52     End Function
    53 
    54     ''' <summary>
    55     ''' 格式化容量大小
    56     ''' </summary>
    57     ''' <param name="size">容量(B)</param>
    58     ''' <returns>已格式化的容量</returns>
    59     Private Shared Function FormatSize(ByVal size As Double) As String
    60         Dim d As Double = size
    61         Dim i As Integer = 0
    62         Do While (d > 1024) AndAlso (i < 5)
    63             d /= 1024
    64             i += 1
    65         Loop
    66         Dim unit() As String = {"B", "KB", "MB", "GB", "TB"}
    67         Return (String.Format("{0} {1}", Math.Round(d, 2), unit(i)))
    68     End Function
    69 End Class
    MemUsage

    参考资料

    1.C#获得Cpu使用率

    2.c# 获取某一个进程的cpu和内存使用情况

  • 相关阅读:
    万能还是万恶的花括号?(PHP)
    深入理解PHP对象赋值
    关联容器常用用法
    顺序容器常用用法
    浏览器安全:35 | 安全沙箱:页面和系统之间的隔离墙
    vue 重学笔记一
    Vue 中 父子组件的生命周期钩子函数的执行顺序
    浏览器中的网络:31 | HTTP/3:甩掉 TCP、TLS 的包袱,构建高效网络
    浏览器安全:34 | CSRF攻击:陌生链接不能随便点
    webpack 打包工具,loader 和 plugin 是什么,是如何实现的
  • 原文地址:https://www.cnblogs.com/towerbit/p/13151865.html
Copyright © 2020-2023  润新知