Jump to content

Function _ProcessListCPU_more


novatek
 Share

Recommended Posts

;~ -------------------------------------------------------
;~ Monitoring more processes on more computers
;~ -------------------------------------------------------
global $oMyError = ObjEvent("AutoIt.Error","_ErrorHandler")  ;set global COM error handler

$sProcess = ""              ;All
;~ $sProcess = "Idle"       ;Other test process names
;~ $sProcess = "_Total"     ;funny one
;~ $sProcess = "ntvdm"      ;DOS process
;~ $sProcess = "AutoIt3"    ;do not assign .exe to process name
;~ $sProcess = 1234         ;PID for process
;~ $sProcess = 0            ;Idle


While 1
    for $f = 0 to 2

        $iTimer1 = timerinit()
        
        ;select one
        if $f = 0 then $aProcessCPU = _ProcessListCPU_more($sProcess, 0)
        if $f = 1 then $aProcessCPU = _ProcessListCPU_more("svchost", 0, "127.0.0.1")
        if $f = 2 then $aProcessCPU = _ProcessListCPU_more("idle", 0, "MyServer_x", "user", "pass")
        
        $iTimer2 = int(TimerDiff($iTimer1))

        $sTip =  _                                      ;display function time duration
                            "      " & @TAB & _
                            $iTimer2 & @TAB & _
                            "..function time in ms" & @LF & @LF
        If $aProcessCPU[0][0] < 0 then                  ;display error
            $sTip = $sTip & _
                            "[0][0]" & @TAB & _
                            $aProcessCPU[0][0] & @TAB & _
                            "Error number" & @LF
            $sTip = $sTip &  _
                            "[0][1]" & @TAB & _
                            $aProcessCPU[0][1] & @TAB & _
                            "" & @LF
            $sTip = $sTip &  _
                            "[0][2]" & @TAB & _
                            $aProcessCPU[0][2] & @TAB & _
                            "" & @LF & @LF
        else                                            ;display summary
            $sTip = $sTip & _
                            "[0][0]" & @TAB & _
                            $aProcessCPU[0][0] & @TAB & _
                            "_ProcessItems" & @LF

            $sTip = $sTip &  _
                            "[0][1]" & @TAB & _
                            $aProcessCPU[0][1] & @TAB & _
                            "_TotalUsed" & @LF

            $sTip = $sTip & _
                            "[0][2]" & @TAB & _
                            $aProcessCPU[0][2] & @TAB & _
                            "_TotalUsedByName" & @LF & @LF 
        endif
                        
        $sTip = $sTip & "PID" & @TAB & "CPU" & @TAB & "Name" & @LF
        
        for $i = 1 to $aProcessCPU[0][0]                ;enuerate process items for display

            $sTip = $sTip & _
                            $aProcessCPU[$i][1] & @TAB & _
                            $aProcessCPU[$i][2] & @TAB & _
                            $aProcessCPU[$i][0] & @LF
        next
            

        tooltip($sTip)
        sleep(1500)     ;set your own sleep time for LOOP mode
    next
WEnd



Func _ProcessListCPU_more($strProcess = "", $iSampleTime = 500, $sComputerName = @ComputerName, $sUser="", $sPassword="")
    
;~      All Parameters are optional:
;~          - All process items will be returned if first parameter is not set
;~          - 500 ms is default sample time
;~          - This computer will be measured by default (set IP or Computer_Name for others)
;~          - User name for connection is Not set by default
;~          - Password for connection is Not set by default
;~      Process could be string ("Name") or PID number (1234)
;~      For NORMAL MODE(one time measuring): set Sample value to more than 0 ms
;~                  ( average CPU usage will be measured during sleep time within function)
;~      For LOOP MODE (continuous measuring): set Sample value to 0 ms
;~                  ( average CPU usage will be measured between two function calls )
;~
;~      Success: Returns 2-D array  $array[0][0] = Number of processes (also upper bound of array)
;~                                  $array[0][1] = Total CPU usage by All Processes
;~                                  $array[0][2] = Total CPU usage by All Processes under given process "Name"
;~
;~                                  $array[1][0] = 1st Process name
;~                                  $array[1][1] = 1st Process ID (PID)
;~                                  $array[1][2] = 1st Process CPU Usage
;~
;~                                  $array[2][0] = 2nd Process name
;~                                  $array[2][1] = 2nd Process ID (PID)
;~                                  $array[2][2] = 2nd Process CPU Usage
;~                                  ...
;~                                  $array[n][0] = nth Process name
;~                                  $array[n][1] = nth Process ID (PID)
;~                                  $array[n][2] = nth Process CPU Usage
;~
;~      Failure: Returns 2-D array  $array[0][0] = ""  ( wrong process name or PID )
;~                                  $array[0][0] = -1  ( process collection not found)
;~                                  $array[0][0] = -2  ( WMI service not found or Computer not found)
;~                                  $array[0][0] = -4  ( computer disconnected )
;~                                  $array[0][1] = "Error description"
;~                                                  ( Access denied - password or username inccorect )
;~                                                  ( RPC server unavailable - no connection or firewall block 
;~                                                    open ports External: 135 and Internal: 1788 for WMI traffic )

    dim $aResultSet[2][3]
    
    if $strProcess = 0 AND IsNumber($strProcess) then $strProcess = "Idle"
    if $iSampleTime = "" AND IsString($iSampleTime) then $iSampleTime = 500
    if $sComputerName = "" then $sComputerName = @ComputerName
    
    
    if not IsDeclared("aProcess") AND $iSampleTime = 0 then     ;first time in loop mode
        $bFirstTimeInLoopMode = 1
    else
        $bFirstTimeInLoopMode = 0
    endif
    
    if not IsDeclared("aProcess") then
        
        global $aProcess[1][1][10000][10]   ;[ Computer query ], [ Process query ], [ PID ],
                                            ;[ nul, PID, name, CPU, iP1, iT1, iP2, iT2, iPP, iTT ]
                                            ;   0    1    2     3    4    5    6    7    8    9
        $aProcess[0][0][0][0] = $sComputerName
        $aProcess[0][0][1][0] = $strProcess

        ;connect WMI first time
        $objLocator = ObjCreate( "WbemScripting.SWbemLocator" )
        $aProcess[0][0][2][0] = $objLocator.ConnectServer ( $sComputerName, "root/cimv2", $sUser, $sPassword )
        
        if @error then
            $aResultSet[0][0] = -2
            $aResultSet[0][1] = $oMyError.description
            return $aResultSet
        endif
                
        $aProcess[0][0][2][0].Security_.impersonationlevel = 3
        
        $aProcess [0][0][4][0] = 1 ;first time flag
    endif


    ; this thing is distingushing between function calls with differnet parameters
    ;(e.g. process name or computer name, but it not need to distinguish sample time changes)

    ;enumerate queries "ComputerName"
    $iUBpn = ubound($aProcess, 2)
    for $iPC = 0 to ubound($aProcess) - 1

        if $aProcess[$iPC][0][0][0] = $sComputerName then
            ExitLoop
        endif

        ;register new computer
        if ubound($aProcess) -1 = $iPC then

            $iPC = $iPC + 1
            redim $aProcess [$iPC +1 ][$iUBpn][10000][10]
            $aProcess [$iPC][0][0][0] = $sComputerName
            
            ;connect WMI on new computer
            $objLocator = ObjCreate( "WbemScripting.SWbemLocator" )
            $aProcess[$iPC][0][2][0] = $objLocator.ConnectServer ( $sComputerName, "root/cimv2", $sUser, $sPassword )
            
            if @error then
                $aResultSet[0][0] = -2
                $aResultSet[0][1] = $oMyError.description
                return $aResultSet
            endif
                
            $aProcess[$iPC][0][2][0].Security_.impersonationlevel = 3
            
            ;set first time flag
            $aProcess [0][0][4][0] = 1

            exitloop
        endif
    next

    ;enumerate queries "ProcessName"
    $iUBpc = ubound($aProcess)
    for $iPN = 0 to ubound($aProcess, 2) - 1

        if $aProcess[$iPC][$iPN][1][0] = $strProcess then
            ExitLoop
        endif
        
        ;register new Process name
        if ubound($aProcess, 2) -1 = $iPN then

            $iPN = $iPN + 1
            redim $aProcess [$iUBpc][$iPN +1 ][10000][10]
            $aProcess [$iPC][$iPN][1][0] = $strProcess
            
            ;set first time flag
            $aProcess [0][0][4][0] = 1
            exitloop
        endif
    next


    ;First Sample
    if $iSampleTime OR  $aProcess [0][0][4][0] = 1 then ;skip if Loop Mode, but not First time
                
        $objWMIService = $aProcess[$iPC][0][2][0]
        
        if IsObj($objWMIService) then
            $colItems = $objWMIService.ExecQuery ("SELECT * FROM Win32_PerfRawData_PerfProc_Process")
        else
            $aResultSet[0][0] = -4
            $aResultSet[0][1] = "Computer disconnected"
            return $aResultSet
        endif

        if not IsObj($colItems) then
            $aResultSet[0][0] = -5
            $aResultSet[0][1] = "WMI Server error"
            return $aResultSet
        endif

        For $objItem In $colItems
            
            $iPID = $objItem.IDProcess
            If $iPID = 0 AND $objItem.Name = "_Total" Then $iPID = 9999

            $aProcess[$iPC][$iPN][$iPID][4] = $objItem.PercentProcessorTime
            $aProcess[$iPC][$iPN][$iPID][5] = $objItem.TimeStamp_Sys100NS
        next

        if  $objItem = "" then
            $aResultSet[0][0] = -1
            $aResultSet[0][1] = "Collection or process not found"
            return $aResultSet
        endif
        
        sleep($iSampleTime)
    endif


    ;Second Sample
    $objWMIService = $aProcess[$iPC][0][2][0]
        
    if IsObj($objWMIService) then
        $colItems = $objWMIService.ExecQuery ("SELECT * FROM Win32_PerfRawData_PerfProc_Process")
    else
        $aResultSet[0][0] = -4
        $aResultSet[0][1] = "Computer disconnected"
        return $aResultSet
    endif
    
    if not IsObj($colItems) then
        $aResultSet[0][0] = -5
        $aResultSet[0][1] = "WMI Server error"
        return $aResultSet
    endif

    $iCountItems = 0 
    $iTotalUsedByName = 0
    $iTotalUsed = 0

    For $objItem In $colItems
        
        if $objItem.Name = "_Total" AND not($strProcess = "_Total") then exitloop
        
        $iPID = $objItem.IDProcess
        If $iPID = 0 AND $objItem.Name = "_Total" Then $iPID = 9999
;~      $aProcess[$iPN][$iPID][1] = $objItem.IDProcess
;~      $aProcess[$iPN][$iPID][2] = $objItem.Name
        $aProcess[$iPC][$iPN][$iPID][6] = $objItem.PercentProcessorTime
        $aProcess[$iPC][$iPN][$iPID][7] = $objItem.TimeStamp_Sys100NS
        
        $aProcess[$iPC][$iPN][$iPID][8] = _                                 ;$iPP = ($iP2 - $iP1)
            $aProcess[$iPC][$iPN][$iPID][6] - $aProcess[$iPC][$iPN][$iPID][4]
            
        $aProcess[$iPC][$iPN][$iPID][9] = _                                 ;$iTT = ($iT2 - $iT1)
            $aProcess[$iPC][$iPN][$iPID][7] - $aProcess[$iPC][$iPN][$iPID][5]
            
        $aProcess[$iPC][$iPN][$iPID][3] = _                 ;$iCPU = round( ($iPP/$iTT) * 100, 0)
            round( ($aProcess[$iPC][$iPN][$iPID][8] / $aProcess[$iPC][$iPN][$iPID][9]) * 100, 0)
                                                                

        $aProcess[$iPC][$iPN][$iPID][4] = $aProcess[$iPC][$iPN][$iPID][6]       ;$iP1 = $iP2
        $aProcess[$iPC][$iPN][$iPID][5] = $aProcess[$iPC][$iPN][$iPID][7]       ;$iT1 = $iT2
        
        ;SumTotalUsed
        if not($objItem.Name = "Idle") AND not($objItem.Name = "_Total") Then
            $iTotalUsed = $iTotalUsed + $aProcess[$iPC][$iPN][$iPID][3]
        endif

        ;Result Set
        if  (($strProcess = "") AND IsString($strProcess)) OR _                     ;strNAME = "", but not 0
            (StringUpper($strProcess) = StringUpper($objItem.Name)) OR _            ;strNAME = objNAME
            (IsNumber($strProcess) AND ($strProcess = $objItem.IDProcess)) then     ;i1234 = obj1234
                        
            $iCountItems += 1
            redim $aResultSet[$iCountItems +1][3]
            $aResultSet[$iCountItems][0] = $objItem.Name
            $aResultSet[$iCountItems][1] = $iPID
            $aResultSet[$iCountItems][2] = $aProcess[$iPC][$iPN][$iPID][3]
            $aResultSet[0][0] = $iCountItems
            
            ;SumTotalByName
            if not($objItem.Name = "Idle") OR ($strProcess = "Idle") Then
                $iTotalUsedByName = $iTotalUsedByName + $aProcess[$iPC][$iPN][$iPID][3]
            endif
        endif
    next

    if  $objItem = "" then
            $aResultSet[0][0] = -1
            $aResultSet[0][1] = "Collection or process not found"
            return $aResultSet
    endif
        
    $aResultSet[0][1] = $iTotalUsed
    $aResultSet[0][2] = $iTotalUsedByName   

    $aProcess [0][0][4][0] = 0 ;reset first time flag

    Return $aResultSet
EndFunc ;==>_ProcessListCPU_more() by novaTek   ...ver 0.02


; COM Error Handler
Func _ErrorHandler()
        
    if $oMyError.number = -2147352567 then          ;expected errors (this one is WMI Server error)
;~  else if $oMyError.number = -1234 then
;~  else if $oMyError.number = -5678 then
    else                                            ;unexpected errors
        Msgbox(0,"","We intercepted an unexpected COM Error !" & @CRLF & @CRLF & _
                    "Error Number is: " & $oMyError.number & @CRLF & _
                    "Description is: " & $oMyError.description & @CRLF & _
                    "Windescription is: " & $oMyError.windescription & @CRLF & _
                    "Source Object is: " & $oMyError.source & @CRLF & _
                    "Script Line Number is: " & $oMyError.scriptline )
        exit
    endif
    
    SetError(1)  ; to check for after this function returns 
Endfunc ;==> _ErrorHandler()

This function is able to monitor more computers and more processes at a time - synchronicaly.

An asynchonous version is here: Func _ProcessListCPU

A simpler, non-array function, for the purpose of measuring only one process at a time, you could find here: Func _ProcessGetCPU()

[Edit] ...ver 0.02

- other computers connecting improvement is added, now you can connect with user name and password

- global error handler is now reqired, so it is attached by

Enjoy!

Search Keywords: Process List CPU ProcessList ProcessListCPU

Edited by novatek
Link to comment
Share on other sites

  • Moderators

Why don't you try keeping the same subject in the same thread that you originally started.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Why don't you try keeping the same subject in the same thread that you originally started.

Hi SmOke_N!

With questions and suggestions, it would be messy in one thread, but there are not many. Anyway, if it would be all the same, I would throw everything in one function, but it is every one special for its purpose.

A question:

I am trying unsuccessfully to connect other computer, with this code:

$objLocator = ObjCreate("WbemScripting.SWbemLocator")
$objConnection = $objLocator.ConnectServer("ComputerName", "root\cimv2", "UserName", "Password")
;or
$objConnection = $objLocator.ConnectServer("198.168.2.100", "root\cimv2", "UserName", "Password")
;==>  The requested action with this object has failed. ($objLocator)
 oÝ÷ Û^­ëaÊ'{
+Çâ殶­s`¢b33c¶ö&¤6öææV7FöâÒb33c¶ö&¤Æö6F÷"ä6öææV7E6W'fW"gV÷C³#rãããgV÷C²ÂgV÷C·&ö÷Bb3#¶6×c"gV÷C²ÂgV÷CµW6W$æÖRgV÷C²ÂgV÷Cµ77v÷&BgV÷C²

What is usually stopping connection, except firewalls, which are all off?

Target is also XP.

Cables are OK, because computers can connect via MS network just fine.

Edited by novatek
Link to comment
Share on other sites

are you sure that tour firewall authorize WMI connections

it's the rule "remote administration"

it opens the port 3389, needed for WMI

it CAN'T be not working

one test that you could do :

try a telnet 192.168.2.100 3389 on your target computer

if you can't, so the port is not opened

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

Hi dear arcker!

Thanks for the first help. It led me to testing with telnet. I have found that Remote Administration must be ON on target computer.

(MyComputer -> Properties -> Remote -> Remote Desktop -> Alow users to connect)

Now the Telnet connects from command prompt:

telnet 192.168.2.100:3389

...and I get command prompt of other computer this way.

I have tried this way:

$objWMIService = $objLocator.ConnectServer ( "OtherComputerName",       "root/cimv2", "user", "pass" )
$objWMIService = $objLocator.ConnectServer ( "OtherComputerName:3389", "root/cimv2", "user", "pass" )
$objWMIService = $objLocator.ConnectServer ( "192.168.2.100",           "root/cimv2", "user", "pass" )
$objWMIService = $objLocator.ConnectServer ( "192.168.2.100:3389",      "root/cimv2", "user", "pass" )
$objWMIService = $objLocator.ConnectServer ( "192.168.2.100:3389",      "root/cimv2")
;==> The requested action with this object has failed.

...but no one of these doesn't work. Any suggestion?

Link to comment
Share on other sites

re man

mmmmm, it's really, really strange

please send me by pm your code

a good test would be to do in your dos console :

wmic /node:yourtargetcomputer /user:yourloginname /password:yourpass OS

if it's work, so no problem

if an error is return, there is a problem

ah and REALLY IMPORTANT :

look in the help, and take the option to avoid com errors

with this, you will know where the problem is, because the error will be returned by wmi itself

take a look at my Remote WMI Control Project in example scripts, to see what i mean (Objevent bla bla bla, my error func, and so on)

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

Hi, thanks for these useful suggestions!

a good test would be to do in your dos console :

wmic /node:yourtargetcomputer /user:yourloginname /password:yourpass OS

if it's work, so no problem

if an error is return, there is a problem

No error returned, so it is near...

ah and REALLY IMPORTANT :

look in the help, and take the option to avoid com errors

with this, you will know where the problem is, because the error will be returned by wmi itself

take a look at my Remote WMI Control Project in example scripts, to see what i mean (Objevent bla bla bla, my error func, and so on)

Good suggestion!

For now I have Run two other similar tools: WBEMTest.exe and WmiMgmt.msc

They show the cause: Access is denied!

(or: The RPC server is unavailable. - when firewall is blocking access)

For firewall settings, I have seen recommendation somewhere, that ports 1788 and 135 are to be opened, for WMI traffic. But for now, I have disabled firewall.

About permissions, I have found this recommendation from user with similar issue.

I finally figured out what the issue was. Everyone must have read and

execute special permissions to the root of c:\. Once I added the special

permissions everything started working like it should.

"Everyone" is a user rule, like "Guest" or "Power User". I have to find, how to add this rule for c:\.

Link to comment
Share on other sites

About permissions, I have found this recommendation from user with similar issue.

I finally figured out what the issue was. Everyone must have read and

execute special permissions to the root of c:\. Once I added the special

permissions everything started working like it should.

"Everyone" is a user rule, like "Guest" or "Power User". I have to find, how to add this rule for c:\.

Yes, I have remembered now, It is in:

Exporer -> Tools -> Folder Options -> View -> Advanced Settings -> Use Simple File Sharing -> set to OFF

Then:

Explorer -> Local disk (C:) -> Properties -> Security -> Group or User Names

I could connect now finally...

$sComputerName = "Other_ComputerName" ;or IP e.g. "192.168.2.100" or "127.0.0.1" for local (this) computer
$sUser = "xxx"
$sPassword = "yyy"

$objLocator = ObjCreate( "WbemScripting.SWbemLocator" )
$objWMIService = $objLocator.ConnectServer ( $sComputerName, "root/cimv2", $sUser, $sPassword )
$objWMIService.Security_.impersonationlevel = 3

$colShares = $objWMIService.ExecQuery( "Select * from Win32_Share" )
For $objShare In $colShares
    msgbox( 0, "", $objShare.Name & " [" & $objShare.Path & "]")
Next

Thiz teknik, it's really very strange ;)

Edited by novatek
Link to comment
Share on other sites

mm really strange, but, i just wonder if you test your function in a domain, or from workgroups.

anyway, i'm able to control my processes from internet

so really strange this c: permission issues

maybe the user, you need to set this :

computername\username (it appears sometime that, depend of the service in wmi you call, you have to set the target computername in credentials)

$objWMIService.Security_.impersonationlevel = 3 ???

no, set it to 6, pktprivacy, better (and default in XP & 2003 => not sure of that, i can't remember evreything Oo)

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Link to comment
Share on other sites

Useful links to inforamtion on WMI managing:

WMI Samples (basic code exmples):

http://www.activxperts.com/activmonitor/wi...nt/wmi/samples/

Windows remote administration tools overview:

http://www.hsc.fr/ressources/breves/win_re...n_tools.html.fr

Complete WMI Reference:

http://www.scriptinternals.com/new/us/default.asp?41001

;)

Edited by novatek
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...