Sven Posted December 10, 2008 Share Posted December 10, 2008 (edited) I keep having a problem with the following code and I can't find out why. It occasionally crashes with an "Line -1: Error: The requested action with this object has failed" message. Here's the scenario for which it is used. There's another program (myApp) that often exits prematurely, however it is required to finish it's job. If myApp quits in less than one minute after it's been started, it is because it's done it's job and doesn't need to run any longer. However the longer it runs, the more likely it will crash. In addition to that, I don't want it to be running when there's nothing for it to do. So I wrote the script below to make sure of several things: 1) if myApp closes before it was running for one minute, I want it to stay closed 2) if myApp was running for longer than one minute when it closed, I want it to be started again Any help on finding out what is causing the error in line -1 message is greatly appreciated. expandcollapse popup#include <array.au3> #include <date.au3> global $msg = "" global $Process global $Process2 global $proc_num Dim $timer[1] = [0] while 1 Dim $timer[1] = [0] sleep(100) ToolTip("waiting for myApp to close", 0, 0) Do $Process = _ProcessListProperties("myApp.exe") sleep(1000) for $i = 1 to $Process[0][0] $aTime = stringsplit($Process[$i][8], " ") $aTime = stringsplit($aTime[$aTime[0]], ":") $ticks_run = _timetoticks(@Hour, @Min, @Sec) - _timetoticks($aTime[1], $aTime[2], $aTime[3]) if $ticks_run >= 45000 Then _arraysearch($timer, $Process[$i][9], 1) if @error then _arrayadd($timer, $Process[$i][9]) EndIf EndIf Next until not processexists("myApp.exe") $timer[0] = ubound($timer) - 1 ToolTip("myApp closed, restarting...", 0, 0) sleep(1000) $msg = "" for $i = 1 to $timer[0] $run = run($timer[$i], "", "", @sw_hide) if not ($run = 0) then $msg = $msg & $i & " & " EndIf Next $msg = stringtrimright($msg, 3) ToolTip("myApp started", 0, 0) sleep(5000) WEnd ;=============================================================================== ; 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: 09/17/2008 -- v2.0.3 ; 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;==>_ProcessListProperties Edited December 10, 2008 by Sven Link to comment Share on other sites More sharing options...
PsaltyDS Posted December 10, 2008 Share Posted December 10, 2008 I keep having a problem with the following code and I can't find out why. It occasionally crashes with an "Line -1: Error: The requested action with this object has failed" message. Here's the scenario for which it is used.There's another program (myApp) that often exits prematurely, however it is required to finish it's job. If myApp quits in less than one minute after it's been started, it is because it's done it's job and doesn't need to run any longer. However the longer it runs, the more likely it will crash. In addition to that, I don't want it to be running when there's nothing for it to do. So I wrote the script below to make sure of several things:1) if myApp closes before it was running for one minute, I want it to stay closed2) if myApp was running for longer than one minute when it closed, I want it to be started againAny help on finding out what is causing the error in line -1 message is greatly appreciated.Add a COM error handler so you can get more info about the error (see help file under OBJ\COM Reference). 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...
Sven Posted December 11, 2008 Author Share Posted December 11, 2008 Read it, and frankly I can't get much out of it. So what you're suggesting is I hook this up with the myApp call and see what happens? Link to comment Share on other sites More sharing options...
PsaltyDS Posted December 11, 2008 Share Posted December 11, 2008 (edited) Read it, and frankly I can't get much out of it. So what you're suggesting is I hook this up with the myApp call and see what happens? Put this near the top of your script (adapted from the help file): Global $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc"); Install a custom error handler Global $f_EventError = 0; COM error flag ; This is my custom error handler Func MyErrFunc() $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 & _ "Script line is: " & $oMyError.scriptline) $f_EventError = 1; something to check for when this function returns EndFunc ;==>MyErrFunc If any COM errors occur during execution of the script, they will be handled by this function instead of crashing your script, and the error number and description can help you debug. If your script needs to check whether a COM error occured, test the $f_EventError flag. P.S. Search the Examples forum for the home topic of the _ProcessListProperties() function, and note the conversation there about Microsoft's memory leak issue with running the SWbemRefresher in a loop. A work around is proposed therein. Edited December 11, 2008 by PsaltyDS 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...
Sven Posted December 12, 2008 Author Share Posted December 12, 2008 Thanks for the advice. To work around the issue, I'm now using while 1 sleep(100) if processexists("myApp.exe") Then $Process = _ProcessListProperties("myApp.exe") for $i = 1 to $Process[0][0] _arrayadd($still_running, $Process[$i][9]) Next $still_running[0] = ubound($still_running) - 1 ToolTip("waiting for myApp to close", 0, 0) Do sleep(100) until not processexists("myApp.exe") ToolTip("myApp closed", 0, 0) sleep(5000) for $i = 1 to $still_running[0] $run = run($still_running[$i], "", "", @sw_hide) ;if not ($run = 0) Then ; $count = $count + 1 ;EndIf Next ToolTip("myApp started", 0, 0) sleep(60000) run("!restartme.exe") exit EndIf WEnd which is working as intended during the last couple of hours. 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