Results 1 to 26 of 26

Thread: Cpu Utilization in vb6

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Dec 2011
    Posts
    23

    Cpu Utilization in vb6

    Name:  PIC20031251114297337.gif
Views: 4754
Size:  8.9 KB


    Code:
    Private Wmi As Object, Locator As Object
    Private PrevCpuTime As Long, SampleRate As Long
    
    
    Private Sub Form_Load()
        SampleRate = 2 'in seconds
        Timer1.Interval = SampleRate * 1000
        Set Locator = CreateObject("WbemScripting.SWbemLocator")
        Set Wmi = Locator.ConnectServer
        Timer1_Timer
    End Sub
    
    
    Private Sub Timer1_Timer()
        Dim Procs As Object, Proc As Object
        Dim CpuTime, Utilization As Single
        Set Procs = Wmi.InstancesOf("Win32_Process")
    
    
        For Each Proc In Procs
    
    
            If Proc.ProcessID = 0 Then 'System Idle Process
                CpuTime = Proc.KernelModeTime / 10000000
    
    
                If PrevCpuTime <> 0 Then
                    Utilization = 1 - (CpuTime - PrevCpuTime) / SampleRate
                    Text1.Text = Format(Utilization, "0.0%")
                End If
                PrevCpuTime = CpuTime
            End If
        Next
    End Sub

  2. #2
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Cpu Utilization in vb6

    When compared against Task Manager, the average values are oftentimes in disagreement. In fact, negative percentages are sometimes displayed. BTW, CpuTime was implicitly declared as a Variant.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  3. #3
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Cpu Utilization in vb6

    Moved to the VB6 CodeBank.

    Quote Originally Posted by Bonnie West View Post
    When compared against Task Manager, the average values are oftentimes in disagreement. In fact, negative percentages are sometimes displayed. BTW, CpuTime was implicitly declared as a Variant.
    That's because the code is completely wrong. What it tries to do is to get the CPU usage information from each running process, but it updates the information inside the loop.

    Say you have 96 running processes (which is what I currently have with all services and apps that runs) then the For Each loop will loop 96 times, but it updates the textbox inside the loop and the only one you will see is the last one, where the PrevCpuTime is set to .... well, who knows? It will be something like the KernelModeTime used by the earlier process, which is not even of interest.

    To get the CPU usage you shouldn't go through the running processes, instead you should get the processor information (as opposed to process information), since modern day computers have more processor cores you have to add them up and then to get an average divide the result with the number of processors in your computer (this isn't perfect since you get an average, but it's close enough).
    Code:
    Private wmi As Object
    
    Private Sub Form_Load()
        Me.Show
        Set wmi = GetObject("winmgmts:\\.\root\CIMV2")
        Timer1.Interval = 1000
        Timer1_Timer
    End Sub
    
    
    Private Sub Timer1_Timer()
        Dim query As Object, counter As Object
        Dim percent As Double
        Set query = wmi.ExecQuery("SELECT * FROM Win32_PerfFormattedData_Counters_ProcessorInformation")
        For Each counter In query
            percent = percent + counter.PercentProcessorTime
        Next
        Text1.Text = Format(percent / query.Count, "0.00") & "%"
    End Sub
    Last edited by Joacim Andersson; Apr 18th, 2013 at 01:51 PM.

  4. #4

    Thread Starter
    Junior Member
    Join Date
    Dec 2011
    Posts
    23

    Re: Cpu Utilization in vb6

    Quote Originally Posted by Joacim Andersson View Post
    Moved to the VB6 CodeBank.

    That's because the code is completely wrong. What it tries to do is to get the CPU usage information from each running process, but it updates the information inside the loop.

    Say you have 96 running processes (which is what I currently have with all services and apps that runs) then the For Each loop will loop 96 times, but it updates the textbox inside the loop and the only one you will see is the last one, where the PrevCpuTime is set to .... well, who knows? It will be something like the KernelModeTime used by the earlier process, which is not even of interest.

    To get the CPU usage you shouldn't go through the running processes, instead you should get the processor information (as opposed to process information), since modern day computers have more processor cores you have to add them up and then to get an average divide the result with the number of processors in your computer (this isn't perfect since you get an average, but it's close enough).
    Code:
    Private wmi As Object
    
    Private Sub Form_Load()
        Me.Show
        Set wmi = GetObject("winmgmts:\\.\root\CIMV2")
        Timer1.Interval = 1000
        Timer1_Timer
    End Sub
    
    
    Private Sub Timer1_Timer()
        Dim query As Object, counter As Object
        Dim percent As Double
        Set query = wmi.ExecQuery("SELECT * FROM Win32_PerfFormattedData_Counters_ProcessorInformation")
        For Each counter In query
            percent = percent + counter.PercentProcessorTime
        Next
        Text1.Text = Format(percent / query.Count, "0.00") & "%"
    End Sub
    your code isnt working and it opens some switch mode

  5. #5
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Cpu Utilization in vb6

    What do you mean with "switch mode". It's working perfectly well on my machine. What Windows version are you using?

  6. #6
    PowerPoster Nightwalker83's Avatar
    Join Date
    Dec 2001
    Location
    Adelaide, Australia
    Posts
    13,344

    Re: Cpu Utilization in vb6

    @JA

    I receive an automation error on this line

    vb Code:
    1. For Each counter In query
    when you quote a post could you please do it via the "Reply With Quote" button or if it multiple post click the "''+" button then "Reply With Quote" button.
    If this thread is finished with please mark it "Resolved" by selecting "Mark thread resolved" from the "Thread tools" drop-down menu.
    https://get.cryptobrowser.site/30/4111672

  7. #7
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Cpu Utilization in vb6

    Tried it again, works fine for me. What Windows version are you running? Try running it with elevated privileges.

  8. #8
    PowerPoster Nightwalker83's Avatar
    Join Date
    Dec 2001
    Location
    Adelaide, Australia
    Posts
    13,344

    Re: Cpu Utilization in vb6

    I'm running the code in an elevated IDE under Window 7 Home.
    when you quote a post could you please do it via the "Reply With Quote" button or if it multiple post click the "''+" button then "Reply With Quote" button.
    If this thread is finished with please mark it "Resolved" by selecting "Mark thread resolved" from the "Thread tools" drop-down menu.
    https://get.cryptobrowser.site/30/4111672

  9. #9
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Cpu Utilization in vb6

    I'm not sure but it might be some required service that's not started by default on home edition. I've executed this on both Win7 and Win8 and it works fine.

  10. #10
    PowerPoster Nightwalker83's Avatar
    Join Date
    Dec 2001
    Location
    Adelaide, Australia
    Posts
    13,344

    Re: Cpu Utilization in vb6

    Suppose I could try it on my Windows 7 Professional laptop and see how it runs.
    when you quote a post could you please do it via the "Reply With Quote" button or if it multiple post click the "''+" button then "Reply With Quote" button.
    If this thread is finished with please mark it "Resolved" by selecting "Mark thread resolved" from the "Thread tools" drop-down menu.
    https://get.cryptobrowser.site/30/4111672

  11. #11
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Cpu Utilization in vb6

    I get the same error on the For Each line as well (on XP). Specifically, the error was wbemErrInvalidClass (0x80041010) - The specified class is not valid. The value for query's Count property was <Invalid class>.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  12. #12
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Cpu Utilization in vb6

    Try this instead and see if you can get it to work.
    Code:
    Private wmi As Object
    
    Private Sub Form_Load()
        Me.Show
        Set wmi = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
        Timer1.Interval = 1000
        Timer1_Timer
    End Sub
    
    
    Private Sub Timer1_Timer()
        Dim query As Object, counter As Object
        Dim percent As Double
        Set query = wmi.ExecQuery("Select * from Win32_Processor")
        For Each counter In query
            percent = percent + counter.LoadPercentage
        Next
        Text1.Text = Format(percent / query.Count, "0.00") & "%"
    End Sub

  13. #13
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Cpu Utilization in vb6

    Quote Originally Posted by Joacim Andersson View Post
    Try this instead and see if you can get it to work.
    Well, now I get Error 94 - Invalid use of Null. counter.LoadPercentage returns Variant/Null.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  14. #14
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Cpu Utilization in vb6

    Well, there's obviously something missing for you to run WMI queries. I'm no expert in that area but both scripts works fine for me.

  15. #15
    PowerPoster
    Join Date
    Aug 2011
    Location
    B.C., Canada
    Posts
    2,887

    Re: Cpu Utilization in vb6

    Quote Originally Posted by Joacim Andersson View Post
    Moved to the VB6 CodeBank.

    That's because the code is completely wrong. What it tries to do is to get the CPU usage information from each running process, but it updates the information inside the loop.

    Say you have 96 running processes (which is what I currently have with all services and apps that runs) then the For Each loop will loop 96 times, but it updates the textbox inside the loop and the only one you will see is the last one, where the PrevCpuTime is set to .... well, who knows? It will be something like the KernelModeTime used by the earlier process, which is not even of interest.

    To get the CPU usage you shouldn't go through the running processes, instead you should get the processor information (as opposed to process information), since modern day computers have more processor cores you have to add them up and then to get an average divide the result with the number of processors in your computer (this isn't perfect since you get an average, but it's close enough).
    Code:
    Private wmi As Object
    
    Private Sub Form_Load()
        Me.Show
        Set wmi = GetObject("winmgmts:\\.\root\CIMV2")
        Timer1.Interval = 1000
        Timer1_Timer
    End Sub
    
    
    Private Sub Timer1_Timer()
        Dim query As Object, counter As Object
        Dim percent As Double
        Set query = wmi.ExecQuery("SELECT * FROM Win32_PerfFormattedData_Counters_ProcessorInformation")
        For Each counter In query
            percent = percent + counter.PercentProcessorTime
        Next
        Text1.Text = Format(percent / query.Count, "0.00") & "%"
    End Sub
    Works for me I'm on Windows 7 Home Premium.

    Copy - Paste, added Timer1 and Text1.

  16. #16
    PowerPoster
    Join Date
    Jul 2006
    Location
    Maldon, Essex. UK
    Posts
    6,334

    Re: Cpu Utilization in vb6

    Using my WMI Browser (http://www.vbforums.com/showthread.p...ser&highlight=) on a Dual Core, 4 Logical Processor machine the _ProcessorInformation query returns 6 records:

    Record 1 'Name' Property = _Total
    Record 2 'Name' Property = 0,_Total
    Record 3 'Name' Property = 0,3
    Record 4 'Name' Property = 0,2
    Record 5 'Name' Property = 0,1
    Record 6 'Name 'Property = 0,0

    I'd guess that only record 1 (or perhaps 2) are actually required. Adding all 6 up and taking the average will not be correct (if I interpret MS's use of the word "Total" correctly)

    Just for fun, I tried 4 methods and unsurprisingly, got 4 different results.
    Code:
    Private wmi As Object
    
    Private Sub Form_Load()
        Me.Show
        Set wmi = GetObject("winmgmts:\\.\root\CIMV2")
        Timer1.Interval = 500
        Timer1_Timer
    End Sub
    
    
    Private Sub Timer1_Timer()
        Dim query As Object, query1 As Object, counter As Object
        Dim percent As Double
        Set query = wmi.ExecQuery("SELECT * FROM Win32_PerfFormattedData_Counters_ProcessorInformation")
        Set query1 = wmi.ExecQuery("Select * from Win32_Processor")
        For Each counter In query
            Select Case counter.Name
                Case "_Total"
                    Text1.Text = "_Total: " & Format(counter.percentprocessortime, "0.00") & "%"
                Case "0,_Total"
                    Text2.Text = "0,_Total: " & Format(counter.percentprocessortime, "0.00") & "%"
                Case Else
                    percent = percent + counter.percentprocessortime
            End Select
        Next
        Text3.Text = "Average of " & CStr(query.Count) & " records: " & Format(percent / query.Count, "0.00") & "%"
        percent = 0
        For Each counter In query1
            percent = percent + counter.LoadPercentage
            Text4.Text = "LoadPercentage(" & counter.numberoflogicalprocessors & "LPs): " & Format(percent, "0.00") & "%"
        Next
    End Sub
    @Bonnie: You may like to run the WMI Browser and see if you can find (in the CIMV2 Namespace) the Classes. I know that some classes have been 'moved about' by MS with various Versions of Windows.

    You should find the Win32_Processor class in:
    CIM_Managed_System_Element -> CIM_LogicalDevice -> CIM_Processor
    The LoadPercentage property is an unsigned 16 bit integer.

    The Win32_PerfFormattedData_Counters_ProcessorInformation class should be found in
    CIM_StatisticalInformation -> Win32_Perf -> Win32_PerfFormattedData

  17. #17
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: Cpu Utilization in vb6

    Quote Originally Posted by Doogle View Post
    @Bonnie: You may like to run the WMI Browser and see if you can find (in the CIMV2 Namespace) the Classes. I know that some classes have been 'moved about' by MS with various Versions of Windows.

    You should find the Win32_Processor class in:
    CIM_Managed_System_Element -> CIM_LogicalDevice -> CIM_Processor
    The LoadPercentage property is an unsigned 16 bit integer.

    The Win32_PerfFormattedData_Counters_ProcessorInformation class should be found in
    CIM_StatisticalInformation -> Win32_Perf -> Win32_PerfFormattedData
    I only had a quick look, but unfortunately, I couldn't find both classes in those locations. I didn't try searching further because I was overwhelmed by the number of available classes. Thanks anyway!
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  18. #18
    Member
    Join Date
    Apr 2009
    Posts
    48

    Re: Cpu Utilization in vb6

    I took Doogle's code and made it so you can query a specific property

    Code:
    Private WMI As Object
    
    'CPU or Core: -1=total of all CPU/Core values, 0 or above=that specific CPU/core value (value = percent processor time)
    'CPU: -2=total # of cores, -3=average of all cores, -4=average Load percentage of all CPUs, -5=summary (text), -6=CSV of all core values
    Public Function CPU_Usage(Optional CPU As Long = -1, Optional Core As Long = -1) As String
        Dim query As Object, query1 As Object, counter As Object, percent As Double, Cores As String, Value As String, Count As Long, Index As Long, Total As String
        If WMI Is Nothing Then Set WMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
        Set query = WMI.ExecQuery("SELECT * FROM Win32_PerfFormattedData_Counters_ProcessorInformation")
        Set query1 = WMI.ExecQuery("Select * from Win32_Processor")
        For Each counter In query
            Value = Format(counter.percentprocessortime, "0.00")
            If CPU = -5 Then Total = Append(Total, counter.Name & "=" & Value, vbNewLine)
            If counter.Name = "_Total" Then 'total of all CPUs
                If CPU = -1 And Core = -1 Then CPU_Usage = Value
            ElseIf EndsWith(counter.Name, ",_Total") Then ' counter.Name = CPU & ",_Total" Then
                Index = Val(Replace(counter.Name, ",_Total", ""))
                If Core = -1 Then CPU_Usage = Value
            Else
                Cores = Append(Cores, Value, ",")
                percent = percent + counter.percentprocessortime
                Count = Count + 1
                If CPU = Index And Core = counter.Name Then CPU_Usage = Value
            End If
        Next
        Select Case CPU
            Case -2: CPU_Usage = Count 'total number of cores
            Case -3: CPU_Usage = Format(percent / Count, "0.00") 'average of all cores
            Case Else
                If Core < -1 Or CPU < 0 Then
                    If CPU = -5 Then Total = Append(Total, ",_avg=" & Format(percent / Count, "0.00"), vbNewLine)
                    percent = 0
                    Index = 0
                    For Each counter In query1
                        Value = Format(counter.LoadPercentage, "0.00")
                        If CPU = -5 Then Total = Append(Total, Index & ",Load=" & Value & vbNewLine & Index & ",Cores=" & counter.numberoflogicalprocessors, vbNewLine)
                        percent = percent + counter.LoadPercentage
                        If CPU = Index Then
                            Select Case Core
                                Case -2: CPU_Usage = counter.numberoflogicalprocessors 'number of cores
                                Case -3: CPU_Usage = Value 'load percentage
                            End Select
                        End If
                        Index = Index + 1
                    Next
                    Select Case CPU
                        Case -4: CPU_Usage = Format(percent / Index, "0.00")
                        Case -5: CPU_Usage = Total & vbNewLine & ",_Cores=" & Count
                        Case -6: CPU_Usage = Cores 'CSV
                    End Select
                End If
        End Select
    End Function

  19. #19
    Hyperactive Member
    Join Date
    Feb 2015
    Location
    Colorado USA
    Posts
    261

    Re: Cpu Utilization in vb6

    Code:
            If CPU = -5 Then Total = Append(Total, counter.Name & "=" & Value, vbNewLine)
    "Append" is not a valid function in VB6 or VBA...

  20. #20
    Member
    Join Date
    Apr 2009
    Posts
    48

    Re: Cpu Utilization in vb6

    Whoops

    Code:
    Public Function Append(ByVal Text As String, ByVal TextToAppend As String, Optional Delimeter As String = "|") As String
        Text = TrimS(Text, Delimeter)
        TextToAppend = TrimS(TextToAppend, Delimeter)
        If Len(Text) = 0 Then
            Append = TextToAppend
        ElseIf Len(TextToAppend) > 0 Then
            Append = Text & Delimeter & TextToAppend
        Else
            Append = Text
        End If
    End Function
    Public Function TrimS(ByVal Text As String, TextToTrim As String) As String
        TrimS = Trim(Text)
        If StartsWith(TrimS, TextToTrim) Then TrimS = Right(TrimS, Len(TrimS) - Len(TextToTrim))
        If EndsWith(TrimS, TextToTrim) Then TrimS = Left(TrimS, Len(TrimS) - Len(TextToTrim))
    End Function
    Public Function StartsWith(Text As String, ToLookFor As String) As Boolean
        StartsWith = InStr(Left(Text, Len(ToLookFor)), ToLookFor) = 1
    End Function
    Public Function EndsWith(Text As String, ToLookFor As String) As Boolean
        EndsWith = Right(Text, Len(ToLookFor)) = ToLookFor
    End Function

  21. #21
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    2,235

    Re: Cpu Utilization in vb6

    WMI cannot be relied upon to be present. I have encountered machines where the whole of the WMI namespaces was missing. An upgrade from Win 7 to Win 10 certainly caused one machine to be in this state. Others have reported WMI corruption or failure to update. The results also seem to be ambiguous and not real-time.

  22. #22
    Member
    Join Date
    Apr 2009
    Posts
    48

    Re: Cpu Utilization in vb6

    I don't like WMI either, it takes like a full second to get CPU stats and that's just terrible for real time applications...

    There's gotta be proper API for this, Task Manager probably doesn't use WMI.

  23. #23
    Hyperactive Member
    Join Date
    Aug 2017
    Posts
    380

    Re: Cpu Utilization in vb6

    Quote Originally Posted by neotechni View Post
    There's gotta be proper API for this, Task Manager probably doesn't use WMI.
    Indeed, there is.

  24. #24
    Member
    Join Date
    Apr 2009
    Posts
    48

    Re: Cpu Utilization in vb6

    Quote Originally Posted by Victor Bravo VI View Post
    Indeed, there is.
    That seems to be code to get the RAM usage of a specific process, this thread is about total CPU usage though

  25. #25
    Hyperactive Member
    Join Date
    Aug 2017
    Posts
    380

    Re: Cpu Utilization in vb6

    Quote Originally Posted by neotechni View Post
    That seems to be code to get the RAM usage of a specific process, this thread is about total CPU usage though
    The Performance Counters API can give you more than just the memory usage of a process — it can also tell you the CPU usage of any process, the utilization of the CPU (including per core/thread stats), disk & network activity, all sorts of system statistics and many more. In the demo in that post, simply uncomment the #Const BrowseforPerformanceCounter line in order to show the Browse Performance Counters dialog where you can choose from a dizzying array of available counters.

  26. #26
    Member
    Join Date
    Apr 2009
    Posts
    48

    Re: Cpu Utilization in vb6

    Interesting,

    I managed to get the popup to show with the list, but no matter what I click the function that's supposed to return the number of characters returns 0 so the path is always empty.

    This would be exactly what I want, if it worked... (Windows 10)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width