PsaltyDS Posted May 5, 2008 Share Posted May 5, 2008 (edited) The _ProcessListProperties() function has been floating around General Help and Support long enough. This is it's new home. This function lists several properties of all processes (default), selected processes by name, or a single process by PID. ===> Important bug note: The SwbemRefresher object has a Microsoft bug that causes a memory leak when called repeatedly. Until a fix is found from Microsoft,don't use _ProcessListProperties() in a tight loop. <===Change Log: 05/05/2008 -- v1.0.0 -- First version placed in Example Scripts 05/07/2008 -- v1.0.1 -- Added the calling command line at [n][9] 06/10/2008 -- v2.0.0 -- Removed use of ProcessList() so remote access could work 06/12/2008 -- v2.0.1 -- Added geeky RegExp for WMI date conversion by weaponx 07/02/2008 -- v2.0.2 -- Fixed find by PID or Name, which was broken by removing ProcessList() usage 09/17/2008 -- v2.0.3 -- Added Debug (SeDebugPrivilege) to WMI call to retrieve fuller results 12/15/2008 -- v2.0.3 -- No change to function, cleaned up demo and added COM error handler to it12/01/2009 -- v2.0.4 -- Fixed check for null $Process so '0' could be used (System Idle Process)Information is returned in a 2D array similar to the native ProcessList(), in fact the UDF uses ProcessList() internally. This is the structure of the array:[0][0] - Number of processes listed (can be 0 if no matches found)[1][0] - 1st process name[1][1] - 1st process PID[1][2] - 1st process Parent PID[1][3] - 1st process owner[1][4] - 1st process priority (0 = low, 31 = high)[1][5] - 1st process executable path[1][6] - 1st process CPU usage[1][7] - 1st process memory usage[1][8] - 1st process creation date/time = "MM/DD/YYY hh:mm:ss"[1][9] - 1st process command line string ...[n][0] thru [n][9] - last process propertiesHere is the function, with a running demo script:expandcollapse popup#include <Array.au3>; Only for _ArrayDisplay() ; Install a custom error handler Global $oMyError = ObjEvent("AutoIt.Error","MyErrFunc"), $f_COMError = False ; Globals Global $avRET, $iPID ; Demonstrate listing all processes $avRET = _ProcessListProperties() _ArrayDisplay($avRET, "All Processes") ; Demonstrate listing by name $avRET = _ProcessListProperties("svchost.exe") _ArrayDisplay($avRET, "By name: 'svchost.exe'") ; Demonstrate listing by PID (integer) $iPID = ProcessExists("svchost.exe") $avRET = _ProcessListProperties($iPID) _ArrayDisplay($avRET, "By int PID: " & $iPID) ; Demonstrate listing by PID (numeric string) $iPID = String($iPID) $avRET = _ProcessListProperties($iPID) _ArrayDisplay($avRET, "By string PID: " & $iPID) ; Demonstrate not found $avRET = _ProcessListProperties("NoSuchProcess.exe") _ArrayDisplay($avRET, "Not found: 'NoSuchProcess.exe'") ; This is my custom error handler Func MyErrFunc() Local $HexNumber=hex($oMyError.number,8) Msgbox(0,"","We intercepted a COM Error !" & @CRLF & _ "Number is: " & $HexNumber & @CRLF & _ "WinDescription is: " & $oMyError.windescription & @CRLF & _ "Source is: " & $oMyError.source & @CRLF & _ "ScriptLine is: " & $oMyError.scriptline) $f_COMError = True; something to check for when this function returns Endfunc ;=============================================================================== ; Function Name: _ProcessListProperties() ; Description: Get various properties of a process, or all processes ; Call With: _ProcessListProperties( [$Process [, $sComputer]] ) ; Parameter(s): (optional) $Process - PID or name of a process, default is "" (all) ; (optional) $sComputer - remote computer to get list from, default is local ; Requirement(s): AutoIt v3.2.4.9+ ; Return Value(s): On Success - Returns a 2D array of processes, as in ProcessList() ; with additional columns added: ; [0][0] - Number of processes listed (can be 0 if no matches found) ; [1][0] - 1st process name ; [1][1] - 1st process PID ; [1][2] - 1st process Parent PID ; [1][3] - 1st process owner ; [1][4] - 1st process priority (0 = low, 31 = high) ; [1][5] - 1st process executable path ; [1][6] - 1st process CPU usage ; [1][7] - 1st process memory usage ; [1][8] - 1st process creation date/time = "MM/DD/YYY hh:mm:ss" (hh = 00 to 23) ; [1][9] - 1st process command line string ; ... ; [n][0] thru [n][9] - last process properties ; On Failure: Returns array with [0][0] = 0 and sets @Error to non-zero (see code below) ; Author(s): PsaltyDS at http://www.autoitscript.com/forum ; Date/Version: 12/01/2009 -- v2.0.4 ; Notes: If an integer PID or string process name is provided and no match is found, ; then [0][0] = 0 and @error = 0 (not treated as an error, same as ProcessList) ; This function requires admin permissions to the target computer. ; All properties come from the Win32_Process class in WMI. ; To get time-base properties (CPU and Memory usage), a 100ms SWbemRefresher is used. ;=============================================================================== Func _ProcessListProperties($Process = "", $sComputer = ".") Local $sUserName, $sMsg, $sUserDomain, $avProcs, $dtmDate Local $avProcs[1][2] = [[0, ""]], $n = 1 ; Convert PID if passed as string If StringIsInt($Process) Then $Process = Int($Process) ; Connect to WMI and get process objects $oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy, (Debug)}!\\" & $sComputer & "\root\cimv2") If IsObj($oWMI) Then ; Get collection processes from Win32_Process If $Process == "" Then ; Get all $colProcs = $oWMI.ExecQuery("select * from win32_process") ElseIf IsInt($Process) Then ; Get by PID $colProcs = $oWMI.ExecQuery("select * from win32_process where ProcessId = " & $Process) Else ; Get by Name $colProcs = $oWMI.ExecQuery("select * from win32_process where Name = '" & $Process & "'") EndIf If IsObj($colProcs) Then ; Return for no matches If $colProcs.count = 0 Then Return $avProcs ; Size the array ReDim $avProcs[$colProcs.count + 1][10] $avProcs[0][0] = UBound($avProcs) - 1 ; For each process... For $oProc In $colProcs ; [n][0] = Process name $avProcs[$n][0] = $oProc.name ; [n][1] = Process PID $avProcs[$n][1] = $oProc.ProcessId ; [n][2] = Parent PID $avProcs[$n][2] = $oProc.ParentProcessId ; [n][3] = Owner If $oProc.GetOwner($sUserName, $sUserDomain) = 0 Then $avProcs[$n][3] = $sUserDomain & "\" & $sUserName ; [n][4] = Priority $avProcs[$n][4] = $oProc.Priority ; [n][5] = Executable path $avProcs[$n][5] = $oProc.ExecutablePath ; [n][8] = Creation date/time $dtmDate = $oProc.CreationDate If $dtmDate <> "" Then ; Back referencing RegExp pattern from weaponx Local $sRegExpPatt = "\A(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(?:.*)" $dtmDate = StringRegExpReplace($dtmDate, $sRegExpPatt, "$2/$3/$1 $4:$5:$6") EndIf $avProcs[$n][8] = $dtmDate ; [n][9] = Command line string $avProcs[$n][9] = $oProc.CommandLine ; increment index $n += 1 Next Else SetError(2); Error getting process collection from WMI EndIf ; release the collection object $colProcs = 0 ; Get collection of all processes from Win32_PerfFormattedData_PerfProc_Process ; Have to use an SWbemRefresher to pull the collection, or all Perf data will be zeros Local $oRefresher = ObjCreate("WbemScripting.SWbemRefresher") $colProcs = $oRefresher.AddEnum($oWMI, "Win32_PerfFormattedData_PerfProc_Process" ).objectSet $oRefresher.Refresh ; Time delay before calling refresher Local $iTime = TimerInit() Do Sleep(20) Until TimerDiff($iTime) >= 100 $oRefresher.Refresh ; Get PerfProc data For $oProc In $colProcs ; Find it in the array For $n = 1 To $avProcs[0][0] If $avProcs[$n][1] = $oProc.IDProcess Then ; [n][6] = CPU usage $avProcs[$n][6] = $oProc.PercentProcessorTime ; [n][7] = memory usage $avProcs[$n][7] = $oProc.WorkingSet ExitLoop EndIf Next Next Else SetError(1); Error connecting to WMI EndIf ; Return array Return $avProcs EndFunc ;==>_ProcessListPropertiesConstructive criticism welcome. Edited December 1, 2009 by PsaltyDS mistersquirrle, ibrahem and BinaryBrother 2 1 Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
weaponx Posted May 6, 2008 Share Posted May 6, 2008 Good old reliable. I give this script a 9.5/10. Link to comment Share on other sites More sharing options...
SinkoDemio Posted May 6, 2008 Share Posted May 6, 2008 cool Link to comment Share on other sites More sharing options...
amokoura Posted May 7, 2008 Share Posted May 7, 2008 (edited) Excellent! Thank you! I was just about to create a WMI script to check out some detailed process information but your script solves the problem. EDIT: An addition I made is to use the "CommandLine" property. That way I can validate the parameters the process has got. Psalty, how about adding an element to the process array: "command line parameters"? Edited May 7, 2008 by amokoura Link to comment Share on other sites More sharing options...
weaponx Posted May 7, 2008 Share Posted May 7, 2008 Excellent! Thank you!I was just about to create a WMI script to check out some detailed process information but your script solves the problem.EDIT:An addition I made is to use the "CommandLine" property. That way I can validate the parameters the process has got. Psalty, how about adding an element to the process array: "command line parameters"?Sounds good to me. Gives it more functionality like Process Explorer. Easy too.$oProc.CommandLine Link to comment Share on other sites More sharing options...
PsaltyDS Posted May 7, 2008 Author Share Posted May 7, 2008 Sounds good to me. Gives it more functionality like Process Explorer. Easy too.$oProc.CommandLineDone.P.S. If you're going to keep poking me in the ribs, at least retract the claws! Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
weaponx Posted May 7, 2008 Share Posted May 7, 2008 Done.P.S. If you're going to keep poking me in the ribs, at least retract the claws! MMMmmm...penguin ribs... Link to comment Share on other sites More sharing options...
FreeRider Posted May 7, 2008 Share Posted May 7, 2008 Well done my friend... This could be useful for me in a near future... Many thanks ... and I give this script a 9,8/10 just to say better than weaponx Proposal of improvement : Make the function to accept wild cards ($avProcProps = _ProcessListProperties("Sy*.*"). If it's possible it could be nice to have this possibility. Bye, FreeRiderHonour & Fidelity Link to comment Share on other sites More sharing options...
PsaltyDS Posted May 7, 2008 Author Share Posted May 7, 2008 Well done my friend... This could be useful for me in a near future... Many thanks ... and I give this script a 9,8/10 just to say better than weaponx Proposal of improvement : Make the function to accept wild cards ($avProcProps = _ProcessListProperties("Sy*.*"). If it's possible it could be nice to have this possibility.Bye,Thanks. The function starts out by calling the native ProcessList(), and then adds more details to the array. So if ProcessList won't take it, then _ProcessListProperties won't. Besides, that is easy to implement in post-processing of the returned array. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
NELyon Posted May 7, 2008 Share Posted May 7, 2008 MMMmmm...penguin ribs...Great with BBQ Sauce Awesome script. I can't believe I haven't seen it if it's been floating around for a while. Link to comment Share on other sites More sharing options...
weaponx Posted May 8, 2008 Share Posted May 8, 2008 My only complaint is that the creation timestamp is in U.S. format instead of Date UDF format (YYYY/MM/DD HH:MM:SS), it would be nice to use _DateDiff() without modifying the output. There is also a cool way to format timestamps returned from WMI. I just put this after the first ObjGet("winmgmts... $oDateTime = ObjCreate("WbemScripting.SWbemDateTime") Then this goes in the process collection loop If $oProc.CreationDate <> "" Then ;Copy process creation timestamp to date/time object $oDateTime.Value = $oProc.CreationDate $FormatDate = StringFormat("%s/%s/%s %s:%s:%s",$oDateTime.Year, $oDateTime.Month, $oDateTime.Day, $oDateTime.Hours, $oDateTime.Minutes, $oDateTime.Seconds) ConsoleWrite("Creation date: " & $FormatDate & @CRLF) EndIf Link to comment Share on other sites More sharing options...
PsaltyDS Posted May 8, 2008 Author Share Posted May 8, 2008 My only complaint is that the creation timestamp is in U.S. format instead of Date UDF format (YYYY/MM/DD HH:MM:SS), it would be nice to use _DateDiff() without modifying the output. There is also a cool way to format timestamps returned from WMI. I just put this after the first ObjGet("winmgmts... $oDateTime = ObjCreate("WbemScripting.SWbemDateTime") Then this goes in the process collection loop If $oProc.CreationDate <> "" Then ;Copy process creation timestamp to date/time object $oDateTime.Value = $oProc.CreationDate $FormatDate = StringFormat("%s/%s/%s %s:%s:%s",$oDateTime.Year, $oDateTime.Month, $oDateTime.Day, $oDateTime.Hours, $oDateTime.Minutes, $oDateTime.Seconds) ConsoleWrite("Creation date: " & $FormatDate & @CRLF) EndIf I like that, very nice! The format currently presented is actually the default from _Now(). Then there are the various _Dat_* UDFs that return a DLL struct! If you get a string with _Date_Time_DOSDateTimeToStr() you still get MM/DD/YYYY. That appears to be more "standard" with AutoIt than _DateDiff() format. I would welcome more input on what the most useful date/time format would be... Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
weaponx Posted May 8, 2008 Share Posted May 8, 2008 (edited) I wish there was a standard datetime format that every function followed. Its frustrating to have to account for more than one.Here is a good reference.http://dev.mysql.com/doc/refman/5.0/en/datetime.htmlAnother cool trick with date/time format.$oDateTime.Value = $oProc.CreationDate With $oDateTime $FormatDate = StringFormat("%s/%s/%s %s:%s:%s",.Year, .Month, .Day, .Hours, .Minutes, .Seconds) EndWithYou're supposed to be able to output $oDateTime.GetVarDate which should be local format but its always WMI format. Edited May 8, 2008 by weaponx Link to comment Share on other sites More sharing options...
jennico Posted June 4, 2008 Share Posted June 4, 2008 (edited) thank you very much for this sripty.I would welcome more input on what the most useful date/time format would be...from the practical point of wiev, the american date standard is the worst.better is DD.MM.YYYY moreover because the time format also uses 24 hour format and not am/pm.but the best way is to sort the format items by size: Year>Month>Day>Hour>Min>Sec. this is the correct scientific use and can be chronologically sorted (if used without separators) without converting it. moreover you can directly calculate the format, e.g. use the difference when converted to integer.so i vote clearly for: YYYY-MM-DD HH:MM:SS or (why not?) YYYYMMDDHHMMSSso now is: 20080604231804cheersj. Edited June 4, 2008 by jennico Spoiler I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.Don't forget this IP: 213.251.145.96 Â Link to comment Share on other sites More sharing options...
amokoura Posted June 5, 2008 Share Posted June 5, 2008 How about putting as many characters as the number indicates. Meaning that 20080604231804 would be YYYYYYYYYYYYY... (2008 times)...YYYYYYYYYYYYYYYMMMMMMDDDDHHHHHHHHHHHHHHHHHHHHMMMMMMMMMMMMMMMMMMSSSS It's boring that people think numbers are COOLER than characters. We need a revolution on this one. Link to comment Share on other sites More sharing options...
weaponx Posted June 5, 2008 Share Posted June 5, 2008 How about putting as many characters as the number indicates. Meaning that 20080604231804 would beYYYYYYYYYYYYY... (2008 times)...YYYYYYYYYYYYYYYMMMMMMDDDDHHHHHHHHHHHHHHHHHHHHMMMMMMMMMMMMMMMMMMSSSSIt's boring that people think numbers are COOLER than characters. We need a revolution on this one.Why did you waste a post for that? Link to comment Share on other sites More sharing options...
jennico Posted June 5, 2008 Share Posted June 5, 2008 (edited) How about putting as many characters as the number indicates. Meaning that 20080604231804 would beYYYYYYYYYYYYY... (2008 times)...YYYYYYYYYYYYYYYMMMMMMDDDDHHHHHHHHHHHHHHHHHHHHMMMMMMMMMMMMMMMMMMSSSSIt's boring that people think numbers are COOLER than characters. We need a revolution on this one.SPAM + IGNORANCE Edited June 5, 2008 by jennico Spoiler I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.Don't forget this IP: 213.251.145.96 Â Link to comment Share on other sites More sharing options...
PsaltyDS Posted June 5, 2008 Author Share Posted June 5, 2008 How about putting as many characters as the number indicates. Meaning that 20080604231804 would beYYYYYYYYYYYYY... (2008 times)...YYYYYYYYYYYYYYYMMMMMMDDDDHHHHHHHHHHHHHHHHHHHHMMMMMMMMMMMMMMMMMMSSSSIt's boring that people think numbers are COOLER than characters. We need a revolution on this one.That's brilliant. I hear The SCO Group is looking for developers, you should send them your resume. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
NELyon Posted June 5, 2008 Share Posted June 5, 2008 How about putting as many characters as the number indicates. Meaning that 20080604231804 would beYYYYYYYYYYYYY... (2008 times)...YYYYYYYYYYYYYYYMMMMMMDDDDHHHHHHHHHHHHHHHHHHHHMMMMMMMMMMMMMMMMMMSSSSIt's boring that people think numbers are COOLER than characters. We need a revolution on this one.Numbers are characters... just numerical characters... Totally irrelevant. Link to comment Share on other sites More sharing options...
duckling78 Posted June 6, 2008 Share Posted June 6, 2008 I have a memory leak in one of my programs and seemed to have narrowed it down to using this function. My program is a program to help testing programs we make that tracks memory, cpu and thread usage over time intervals. It uses _ProcessListProperties to check CPU usage for a specified executable. Is there a memory leak? Here is an example script showing memory usage blowing up from calling this function. (Paste the _ProcessListProperties function at the end of the script) #include <array.au3> While 1 $array = _ProcessListProperties("AutoIt3.exe") ;Replace "AutoIt3.exe" with any running process If IsArray($array) Then For $i = 0 To UBound($array, 2) - 1 Switch $i Case 0 $string = $array[1][0] Case Else $string = $string & @TAB & $array[1][$i] EndSwitch Next ConsoleWrite("_ArrayToString($array): " & $string & @CRLF) Else ConsoleWrite("$array: " & $array & @CRLF) EndIf WEnd Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now