ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

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

2020-06-17 13:03:15  阅读:364  来源: 互联网

标签:Dim VB End INFORMATION Windows SYSTEM Private system NET


.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和内存使用情况

标签:Dim,VB,End,INFORMATION,Windows,SYSTEM,Private,system,NET
来源: https://www.cnblogs.com/towerbit/p/13151865.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有