none
Vbscript to retrieve the CPU usage percentage of each process

    Question

  • Hello,

    i want to write a vbscript that will retrieve the CPU Percentage of each process. It has to be a vbscript.

    I want the results to be simillar to the ones shown on the task manager. Again, not the same, but similiar - good enough to represent

    what's really happening. I've read tons of posts on this issue and all of them were inconsistent.

    Some recommended using Win32_PerfRawData_PerfProc_Process, While others recommended using Win32_PerfFormattedData_PerfProc_Process.

    Some recommended using the percentUserTime property and others recommended using the percentProcessorTime Property

    Some say that it is enough the get the single value, while others say that i have to get two values at an interval, and get an average.

    So, i am not sure as to what is the best way to get TRUE values. I tried many different combinations and the one that makes

    most sense is this one:

        Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2") 
        Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process",,48)
         
    For Each process In ColItems
    
      WScript.echo Process.name & " " & CPUUSage(Process.Handle) & "%"   
    Next
    
    Function CPUUSage( ProcID )
      On Error Resume Next
      Set objService = GetObject("Winmgmts:{impersonationlevel=impersonate}!\Root\Cimv2")
    
       For Each objInstance1 in objService.ExecQuery("Select * from Win32_PerfFormattedData_PerfProc_Process  where IDProcess = '" & ProcID & "'")
           N1 = objInstance1.PercentProcessorTime
         Exit For
       Next
    
    WScript.Sleep(1000)
    
       For Each perf_instance2 in objService.ExecQuery("Select * from Win32_PerfFormattedData_PerfProc_Process  where IDProcess = '" & ProcID & "'")
           N2 = perf_instance2.PercentProcessorTime
         Exit For
       Next
       WScript.Echo CInt(N2) & ":" & CInt(N1)
    
      ' CounterType - PERF_100NSEC_TIMER_INV
      ' Formula - (1- ((N2 - N1) / (D2 - D1))) x 100
      ' Didn't use formula - moved to Formatted Data
        Nd = (CInt(N2) + CInt(N1)) / 2
    
      CPUUSage = Round(Nd ,0)
    End Function
    
     

    So.. in this script i set an interval of one second, i sampled The formatted data twice, used the percentProcessorTime property and averaged it to get the result.

    Is this the best way to achieve my goal (getting values that are close enough to real ones)?

    Should the interval be longer? ideally, it would.. but i don't want the script to run for ages...

    I'm sure this is unclear to many people,

    any bottom line answer would be great.

    Thanks.


    Monday, March 05, 2012 9:03 AM

Answers

  • All the experienced Partners and so on here have never encountered a solution for this issue? via vbscript, or another scripting language?

    I'm sure this is an issue for many administrators.. Maybe this is the day that we solve it for them all :)

    The simple answer to your question is that there is no problem.  This is by design and requires that you use the counters as intended but that you first understand perfomance monitoring in its entirety.

    Read and follow the links I posted.  It should become clear after you experiment a bit more.

    I have always recommended use of perfmon or pmon as all of this is handled for you by the tools.  The tool forces you to set up the counters before querying them and then gives you results.  With WMI this is much more difficult and will always depend on what you mean by 'percent' of something that is dynamic as opposed to something like a pie which has a fixed value for percentage.

    Think of it this way.  WHat perceant is you age of the age of teh moon? The sun? Canyou even begin to calculate that.

    Percent in performance monitoring always means percent of the monitored interval as compared to the whole interval.  To obtain an interval it is necessary to have a minimum of two measurements.


    ¯\_(ツ)_/¯

    Saturday, March 10, 2012 8:24 PM

All replies

  • The way you are currently doing it is that you pause 1 second between every WMI query. It would be significantly faster if you just fired off a single query and filter your data from that one query.
    Monday, March 05, 2012 10:15 AM
    Moderator
  • @Momer,

    This question has been answered previously (and very well) by Richard Mueller here:

    http://social.technet.microsoft.com/Forums/en/ITCG/thread/8bcbd793-0423-4f26-bcd7-413d9c0b068a

    If you want the display in a Task Manager-like way, I'd recommend using an HTA with these vbscript functions and using the Timer object to continually refresh, display the data.  Here is a good primer on HTAs that covers grabbing some process level information (staticly):

    http://technet.microsoft.com/en-us/library/ee692768.aspx

    You can very easily modify this to grab/update the information based on the Timer object to "refresh" the data.  I'm sure there is probably already an HTA version of TaskManager out there but my 2-second internet search didn't find one. 

    

    Monday, March 05, 2012 3:42 PM
  • Hey,

    i saw the link before, tried it and the results didn't add up. 

    I checked this script from the link you posted:

    Option Explicit
    Dim strComputer, intPasses, intPause, objWMIService
    Dim objRefresher, colItems, objItem, i
    strComputer = "."
    intPasses = 5
    intPause = 1000 'milliseconds
    Set objWMIService = GetObject("winmgmts:" _
        & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    set objRefresher = CreateObject("WbemScripting.SWbemRefresher")
    Set colItems = objRefresher.AddEnum _
        (objWMIService, "Win32_PerfFormattedData_PerfProc_Process").objectSet
    objRefresher.Refresh
    For i = 1 to intPasses
        Wscript.Sleep intPause
        Wscript.Echo vbCrLf & "Pass " & i
        Wscript.Echo Now
        For Each objItem in colItems
            objRefresher.Refresh
            Wscript.Echo vbCrLf & "Name: " & objItem.Name
            Wscript.Echo "  Creating Process ID: " & objItem.CreatingProcessID
            Wscript.Echo "  Percent Processor Time: " & _
                objItem.PercentProcessorTime
        Next
    Next
    

    The results don't make sense. Idle is almost always at a 100, even if other processe are above 0.

    On the other hand - Total_ isn't always a 100 and sometimes returns 0.

    i don't actually need the results to look like the task manager,

    i just want to get values, that are close to representing the real values at a given time and that make sense,

    which means that all the values combined will add up to a 100.. and that idle won't always be a 100 percent (whenever the processor is busy, ofcourse..)

    Friday, March 09, 2012 11:57 AM
  • Hi

    We've been using the WMI method to enumerate what % of CPU procces are taking up for a while now, and I can catagorically say it doesn't produce accurate results.

    I'd be very interested to know if anyone else has another, more accurate, method though.

    I know it's not scripting but as an alternative I've thought about doing as a replacement is using logman.exe to set up alerts on end devices, so any process that uses over 30% of the CPU for over 10 seconds gets reported in the event log. I could then use event forwarding to report on it.

    http://blogs.technet.com/b/askperf/archive/2008/05/13/two-minute-drill-logman-exe.aspx

    http://blogs.technet.com/b/wincat/archive/2008/08/11/quick-and-dirty-large-scale-eventing-for-windows.aspx

    Cheers

    Alex

    Friday, March 09, 2012 1:34 PM
  • This issue comes up repeatedly with attempts to monitor processes.  An understanding of how a computer system allocates processor time and what the numbers mean in the context of the system is required.  Standard kitchen logic does not apply here.

    The best way to begin to understand how these things are measured by th eOS is to use either Perfmon or the MS utility pmon.

    In perfmon just add all processes to a graph and watch the historical usage.  After some time you will begin to understand what it is telling you.

    With pmon just type pmon at a prompt.  It will list all process and percentages and refresh the screen every few seconds of whenever you hit a key.

    As for %Idle - it will nearly always be 100% because the snapshots are always taken in such a way as to show idle when it is not being run.  This is a by product of trying to watch a running system and is normal.  Even very busy system will not show idle below 100% except very occasionally.

    Think about it like the Heisenberg Uncertainty Principle of Computer Process 'watching'.  Or think about it like a standard 'kitchen' logic issue - "A watched pot never boils";)


    ¯\_(ツ)_/¯

    Friday, March 09, 2012 4:56 PM
  • Hey JRV.

    OK, so now everyone understands...

    but still, there is no way to get the results we're after? At the end of the day, the WMI query is supposed to get the results from the perfmon.

    And Windows manages to do it, since the Task Manager shows results that are logical, even for kitchen logic.

    So, all i want to accomplish is something similar to that.. it doesn't have to be exactly like perfmon or task manager, but something that will make

    some "kitchen logic" and will represent that data.

    All the experienced Partners and so on here have never encountered a solution for this issue? via vbscript, or another scripting language?

    I'm sure this is an issue for many administrators.. Maybe this is the day that we solve it for them all :)

    Saturday, March 10, 2012 9:23 AM
  • Hey JRV.

    OK, so now everyone understands...

    but still, there is no way to get the results we're after? At the end of the day, the WMI query is supposed to get the results from the perfmon.

    And Windows manages to do it, since the Task Manager shows results that are logical, even for kitchen logic.

    So, all i want to accomplish is something similar to that.. it doesn't have to be exactly like perfmon or task manager, but something that will make

    some "kitchen logic" and will represent that data.

    All the experienced Partners and so on here have never encountered a solution for this issue? via vbscript, or another scripting language?

    I'm sure this is an issue for many administrators.. Maybe this is the day that we solve it for them all :)

       

    Perfmon is not the source of the values.  Perfmon is an application that accesses the Window performance subsystem through the Windows API.  Taskman does the same as does WMI.

    Performance counters for processes are created by Windows when  a process is created and stats are gathered into memory.  The API can be used to retrieve the values.  The values are all raw and need to be converted into useful representations of time or percentage. Perfmon, taskman and WMI manipulate these raw values to produce human usable output; each does this in its own way.

    WMI displays two sets of counters for every measurement.  They are labeled ‘RawData’ and ‘FormattedData’.  The values are tagged over an interval when they are cooked.

    To get very low and very jittery readings it is necessary to use the API directly.  I recommend using either pmon or procmon or using perfmon to dump that data and then read the raw data and make your own calculations.

    There are whole books written on this subject.  It is not trivial,


    ¯\_(ツ)_/¯




    Try using PowerSHell and Get-Process to get a very stable view of process statistics. It, too, will give you 100% for idle most of the time.

    • Edited by jrv Saturday, March 10, 2012 7:49 PM
    Saturday, March 10, 2012 7:46 PM
  •  

    The percentage counters are calculated on teh fly in WMI. and require that we use the refresher object to get a timespan over which to calculate the values.

    The perf counters require 'cooking' which will tell them how to calculate the result.  Note that unless you 'cook' matches Taskman or Perfmon 'cookin' you will never match the counters.

    ProcesorTIme requires a set of qualifiers to make the 'cook' go as needed. They are:

    Qualifiers:
    CookingType ("PERF_100NSEC_TIMER") ,
    Counter ("PercentProcessorTime") ,
    PerfTimeStamp ("TimeStamp_Sys100NS") ,
    PerfTimeFreq ("Frequency_Sys100NS")

    Used correctly we can 'predict' the percentage we need.

    For more details on this requirement: http://msdn.microsoft.com/en-us/library/windows/desktop/aa394277(v=vs.85).aspx

    I just stumbled over a very good explanation of this process:

    http://blogs.technet.com/b/heyscriptingguy/archive/2005/04/21/why-does-my-performance-monitoring-script-keep-returning-the-same-incorrect-values.aspx

    You will note when running the code example that refreshes with return values.  Short refresh intervals or a quiet system will return mostly zero values and 100% for ‘Idle’.  This is what you will see in Perfmon when using a short refresh interval.  Use a long interval and the counts will go up.

    This is just how performance monitoring works.  I know it is counter-intuitive but, once you have thought it through, this is the only way it can work.

    There is NO historical percentage counter anywhere in the system.  It is a dynamically derived value.  Yu cannot just query it anywhere with any tool.  Any tool that show historical percentage either keeps its own counter or is just displaying the history since the tool was started.


    ¯\_(ツ)_/¯

    Saturday, March 10, 2012 8:18 PM
  • All the experienced Partners and so on here have never encountered a solution for this issue? via vbscript, or another scripting language?

    I'm sure this is an issue for many administrators.. Maybe this is the day that we solve it for them all :)

    The simple answer to your question is that there is no problem.  This is by design and requires that you use the counters as intended but that you first understand perfomance monitoring in its entirety.

    Read and follow the links I posted.  It should become clear after you experiment a bit more.

    I have always recommended use of perfmon or pmon as all of this is handled for you by the tools.  The tool forces you to set up the counters before querying them and then gives you results.  With WMI this is much more difficult and will always depend on what you mean by 'percent' of something that is dynamic as opposed to something like a pie which has a fixed value for percentage.

    Think of it this way.  WHat perceant is you age of the age of teh moon? The sun? Canyou even begin to calculate that.

    Percent in performance monitoring always means percent of the monitored interval as compared to the whole interval.  To obtain an interval it is necessary to have a minimum of two measurements.


    ¯\_(ツ)_/¯

    Saturday, March 10, 2012 8:24 PM
  • i have yet to read the links u posted and i will do so right now..

    But i've seen many scripts that take raw data and perform some calculation over two measurements. They also use some of the WMI qualifiers that you mentioned.

    is that a possible way to get reasonable percentage results? 

    ' CounterType - PERF_100NSEC_TIMER_INV ' Formula - (1- ((N2 - N1) / (D2 - D1))) x 100

    This is the formula i've seen. N2 and N! are the percentprocessor values and D2 and D1 are one of the qualifiers u mentioned.

    Saturday, March 10, 2012 11:10 PM