Jump to content

script throws me a -1 error occasionally, don't know why


Sven
 Share

Recommended Posts

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.

#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 by Sven
Link to comment
Share on other sites

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.

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

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 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

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

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...