mlowery Posted July 19, 2009 Share Posted July 19, 2009 This should be simple, but I'm not getting it today....I'm doing processing on large MP3s using DOS command-line applications.I want to run each as DOS command, using Run instead of RunWait because as soon as the process exists, I want to immediately change the priority of the process to idle so it doesn't hog the processor. After the priority is set, however, I'd like to wait until the process completes, but report the DOS exit code.Run returns the PID instead of the errorcode like RunWait. I can use the STDERR flag with Run, but it returns error text instead of error codes.How do I get the original numeric DOS error code when using Run instead of RunWait?Example code below works, but I don't know how to access the actual error code. The code below returns "1" as an error code if any error text is received in the ERR channel (regardless of actual DOS error code), and "0" if nothing is in the ERR channel.Enum $PROCESS_PRIORITY_IDLE = 0, $PROCESS_PRIORITY_BELOW_NORMAL, $PROCESS_PRIORITY_NORMAL, $PROCESS_PRIORITY_ABOVE_NORMAL, $PROCESS_PRIORITY_HIGH, $PROCESS_PRIORITY_REALTIME Func _RunDOSPriority($sCommand, $sPath = "", $showFlag = @SW_HIDE, $waitFlag = False, $iPriority = $PROCESS_PRIORITY_NORMAL, $sIO = 0) Local $line, $pid If $waitFlag = True Then $sIO = 4 $pid = Run(@ComSpec & " /C " & $sCommand, $sPath, $showFlag, $sIO) ProcessWait($pid) If $iPriority >= $PROCESS_PRIORITY_IDLE And $iPriority <= $PROCESS_PRIORITY_REALTIME Then ProcessSetPriority($pid, $iPriority) If $waitFlag Then ProcessWaitClose($pid) While 1 $line = StderrRead($pid) If @error Then Return 0 Return SetError(1, 0, 1) ;if any errtxt read, then report errcode 1 (not sure how to report actual errcode as from runwait) WEnd Else Return $pid EndIf EndFunc Link to comment Share on other sites More sharing options...
trung0407 Posted July 20, 2009 Share Posted July 20, 2009 Maybe you should have a look on machine code ASM to see what byte, data represent the exit code. Then you could capture that exit code using StdoutRead Link to comment Share on other sites More sharing options...
bo8ster Posted July 20, 2009 Share Posted July 20, 2009 after $line = StderrRead($pid), ConsoleWriteError($line) you might get something. Also try using _RunDos(). Post your code because code says more then your words can. SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y. Use Opt("MustDeclareVars", 1)[topic="84960"]Brett F's Learning To Script with AutoIt V3[/topic][topic="21048"]Valuater's AutoIt 1-2-3, Class... is now in Session[/topic]Contribution: [topic="87994"]Get SVN Rev Number[/topic], [topic="93527"]Control Handle under mouse[/topic], [topic="91966"]A Presentation using AutoIt[/topic], [topic="112756"]Log ConsoleWrite output in Scite[/topic] Link to comment Share on other sites More sharing options...
Danny35d Posted July 20, 2009 Share Posted July 20, 2009 The following functions I found it in AutoIt3Wrapper.au3 expandcollapse popup;=============================================================================== ; ; Function Name: _ProcessExitCode() ; Description: Returns a handle/exitcode from use of Run(). ; Parameter(s): $i_Pid - ProcessID returned from a Run() execution ; $h_Process - Process handle ; Requirement(s): None ; Return Value(s): On Success - Returns Process handle while Run() is executing ; (use above directly after Run() line with only PID parameter) ; - Returns Process Exitcode when Process does not exist ; (use above with PID and Process Handle parameter returned from first UDF call) ; On Failure - 0 ; Author(s): MHz (Thanks to DaveF for posting these DllCalls in Support Forum) ; ;=============================================================================== ; Func _ProcessExitCode($i_Pid, $h_Process = 0) ; 0 = Return Process Handle of PID else use Handle to Return Exitcode of a PID Local $v_Placeholder If Not IsArray($h_Process) Then ; Return the process handle of a PID $h_Process = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'int', 0x400, 'int', 0, 'int', $i_Pid) If Not @error Then Return $h_Process Else ; Return Process Exitcode of PID $h_Process = DllCall('kernel32.dll', 'ptr', 'GetExitCodeProcess', 'ptr', $h_Process[0], 'int*', $v_Placeholder) If Not @error Then Return $h_Process[2] EndIf Return 0 EndFunc ;==>_ProcessExitCode Func _ProcessCloseHandle($h_Process) ; Close the process handle of a PID DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $h_Process) If Not @error Then Return 1 Return 0 EndFunc ;==>_ProcessCloseHandle Func ShowStdOutErr($l_Handle, $ShowConsole = 1) Local $Line, $tot_out, $err1 = 0, $err2 = 0 Do Sleep(10) $Line = StdoutRead($l_Handle) $err1 = @error $tot_out &= $Line If $ShowConsole Then ConsoleWrite($Line) $Line = StderrRead($l_Handle) $err2 = @error $tot_out &= $Line If $ShowConsole Then ConsoleWrite($Line) Until $err1 And $err2 Return $tot_out EndFunc ;==>ShowStdOutErr Example#include <Constants.au3> $Pid = Run(@ComSpec & ' /c dir /g', @WindowsDir, @SW_SHOW, $STDERR_CHILD + $STDOUT_CHILD) $Handle = _ProcessExitCode($Pid) ShowStdOutErr($Pid) $ExitCode = _ProcessExitCode($Pid, $Handle) _ProcessCloseHandle($Handle) MsgBox(0, "Program returned with exit code:", $ExitCode) $Pid = Run(@ComSpec & ' /c dir', @WindowsDir, @SW_SHOW, $STDERR_CHILD + $STDOUT_CHILD) $Handle = _ProcessExitCode($Pid) ShowStdOutErr($Pid) $ExitCode = _ProcessExitCode($Pid, $Handle) _ProcessCloseHandle($Handle) MsgBox(0, "Program returned with exit code:", $ExitCode) AutoIt Scripts:NetPrinter - Network Printer UtilityRobocopyGUI - GUI interface for M$ robocopy command line Link to comment Share on other sites More sharing options...
trung0407 Posted July 20, 2009 Share Posted July 20, 2009 Nice. But how come I didn't see the function _ProcessExitCode in the help file !!? Link to comment Share on other sites More sharing options...
mlowery Posted July 20, 2009 Author Share Posted July 20, 2009 ; Function Name: _ProcessExitCode()That looks like the solution! I'll give it a try. Thanks! Link to comment Share on other sites More sharing options...
herewasplato Posted July 21, 2009 Share Posted July 21, 2009 Nice. But how come I didn't see the function _ProcessExitCode in the help file !!?As far as I can tell, AutoIt3Wrapper.au3 is not part of the standard distribution, so the UDFs inside AutoIt3Wrapper.au3 would not be in the help file. [size="1"][font="Arial"].[u].[/u][/font][/size] Link to comment Share on other sites More sharing options...
PsaltyDS Posted August 24, 2009 Share Posted August 24, 2009 I think the code shown tries to get too cute with the input parameter. Here's a more simplified version. This demo kicks off two ping processes, one succeeds and the second fails. It displays the PIDs, the process handles, and the exit codes for both: expandcollapse popup$iRunPID1 = Run("ping.exe 127.0.0.1") ; Good ping $iRunPID2 = Run("ping.exe 169.254.1.2") ; Bad ping ConsoleWrite("$iRunPID1 = " & $iRunPID1 & ", $iRunPID2 = " & $iRunPID2 & @LF) $hRun1 = _ProcessGetHandle($iRunPID1) $hRun2 = _ProcessGetHandle($iRunPID2) ConsoleWrite("$hRun1 = " & $hRun1 & ", $hRun2 = " & $hRun2 & @LF) ; Wait for both to finish... ProcessWaitClose($iRunPID1) ProcessWaitClose($iRunPID2) $iExit1 = _ProcessGetExitCode($hRun1) $iExit2 = _ProcessGetExitCode($hRun2) _ProcessCloseHandle($hRun1) _ProcessCloseHandle($hRun2) ConsoleWrite("$iExit1 = " & $iExit1 & ", $iExit2 = " & $iExit2 & @LF) ; Return handle of given PID Func _ProcessGetHandle($iPID) Local Const $PROCESS_QUERY_INFORMATION = 0x0400 Local $avRET = DllCall("kernel32.dll", "ptr", "OpenProcess", "int", $PROCESS_QUERY_INFORMATION, "int", 0, "int", $iPID) If @error Then Return SetError(1, 0, 0) Else Return $avRET[0] EndIf EndFunc ;==>_ProcessGetHandle ; Close process handle Func _ProcessCloseHandle($hProc) Local $avRET = DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProc) If @error Then Return SetError(1, 0, 0) Else Return 1 EndIf EndFunc ;==>_ProcessCloseHandle ; Get process exit code from handle Func _ProcessGetExitCode($hProc) Local $t_ExitCode = DllStructCreate("int") Local $avRET = DllCall("kernel32.dll", "int", "GetExitCodeProcess", "ptr", $hProc, "ptr", DllStructGetPtr($t_ExitCode)) If @error Then Return SetError(1, 0, 0) Else Return DllStructGetData($t_ExitCode, 1) EndIf EndFunc ;==>_ProcessGetExitCode >_< 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...
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