Jump to content

Recommended Posts

Posted (edited)

,,in the help area I gave some advice and oops !, ..it works for me because I extended the code but did not share it 😅

So here is the extended code that I call "UDF". Is not up to AutoIt UDF standards but, it runs. ( anyone willing to bring it up to standards, I'll edit this and place your version 😇 )

Spoiler
#include-once ; #include <_RunWaitEx.au3>
#AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
#include <GuiEdit.au3>
;~ #include <WinAPISysWin.au3>

;~ #include <AutoItConstants.au3> ; needed For $STDERR_CHILD & $STDOUT_CHILD
Global $__g_RunWaitEx_Version = 20250119 ; https://www.autoitscript.com/forum/topic/212643-_runwaitex-udf/
Global $__g_RunWaitEx_DefaultQueueMax = -1
Global $__g_RunWaitEx_LoopFunc = 0
Global $__g_RunWaitEx_LoopFuncDo = 0
Global $__g_RunWaitEx_ProcessClose = 0
Global $__g_RunWaitEx_Default_sWorkingDir = @TempDir
Global $__g_RunWaitEx_Default_iShowFlag = @SW_HIDE
Global $__g_RunWaitEx_Default_iOptFlag = 8 ; 6 ; "BitOR($STDERR_CHILD, $STDOUT_CHILD) = 6"
Global $__g_RunWaitEx_Default_msTimeout = 0
Global $__g_RunWaitEx_Default_iCtrlEdit = 0 ; for GUICtrlCreateEdit()
Global $__g_RunWaitEx_Last_sStderr = "", $__g_RunWaitEx_Last_sStdout = "", $__g_RunWaitEx_Last_iPID = 0
Global $__g_RunWaitEx_Last_iError = 0, $__g_RunWaitEx_Last_iExtended = 0, $__g_RunWaitEx_Last_hPID = 0
Global $__g_RunWaitEx_Default_iConsoleWrite = Int(Not @Compiled)

; these helper functions return the set values, or sets the values if provided with one.
Func _RunWaitEx_Version()
    Return $__g_RunWaitEx_Version
EndFunc   ;==>_RunWaitEx_Version

Func _RunWaitEx_ProcessClose($iVal = Default)
    Local $iError = 0
    If $iVal <> Default Then ; note to self: do this type of checking everywhere
        If IsInt($iVal) Then
            $__g_RunWaitEx_ProcessClose = $iVal
        Else
            $iError = 1
        EndIf
    EndIf
    Return SetError($iError, 0, $__g_RunWaitEx_ProcessClose)
EndFunc   ;==>_RunWaitEx_ProcessClose

Func _RunWaitEx_DefaultQueueMax($iVal = Default)
    If $iVal <> Default Then $__g_RunWaitEx_DefaultQueueMax = $iVal
    Return $__g_RunWaitEx_DefaultQueueMax
EndFunc   ;==>_RunWaitEx_DefaultQueueMax

Func _RunWaitEx_DefaultLoopFunc($func = Default)
    If IsFunc($func) Then
        $__g_RunWaitEx_LoopFunc = $func
        $__g_RunWaitEx_LoopFuncDo = 1
    Else
        If $func <> Default Then
            $__g_RunWaitEx_LoopFunc = ""
            $__g_RunWaitEx_LoopFuncDo = 0
        EndIf
    EndIf
    Return SetError(0, IsFunc($__g_RunWaitEx_LoopFunc), FuncName($__g_RunWaitEx_LoopFunc))
EndFunc   ;==>_RunWaitEx_DefaultLoopFunc

Func _RunWaitEx_DefaultWorkingDir($sVal = Default)
    If $sVal <> Default Then $__g_RunWaitEx_Default_sWorkingDir = String($sVal)
    Return $__g_RunWaitEx_Default_sWorkingDir
EndFunc   ;==>_RunWaitEx_DefaultWorkingDir

Func _RunWaitEx_DefaultShowFlag($iVal = Default)
    If $iVal <> Default Then $__g_RunWaitEx_Default_iShowFlag = Int($iVal)
    Return $__g_RunWaitEx_Default_iShowFlag
EndFunc   ;==>_RunWaitEx_DefaultShowFlag

Func _RunWaitEx_DefaultOptFlag($val = Default)
    If $val <> Default Then $__g_RunWaitEx_Default_iOptFlag = Int($val)
    Return $__g_RunWaitEx_Default_iOptFlag
EndFunc   ;==>_RunWaitEx_DefaultOptFlag

Func _RunWaitEx_DefaultTimeout($val = Default)
    If $val <> Default Then $__g_RunWaitEx_Default_msTimeout = Int($val)
    Return $__g_RunWaitEx_Default_msTimeout
EndFunc   ;==>_RunWaitEx_DefaultTimeout

Func _RunWaitEx_DefaultCtrlEdit($CtrlId = Default) ; v20250119
    Local $iError = 0
    If $CtrlId <> Default Then
        If __RunWaitEx_WinAPI_GetClassName($CtrlId) = "Edit" Then
            $__g_RunWaitEx_Default_iCtrlEdit = Int($CtrlId)
        Else
            $iError = 1
        EndIf
    EndIf
    Return SetError($iError, 0, $__g_RunWaitEx_Default_iCtrlEdit)
EndFunc   ;==>_RunWaitEx_DefaultCtrlEdit

Func _RunWaitEx_DefaultConsoleWrite($val = Default)
    If $val <> Default Then $__g_RunWaitEx_Default_iConsoleWrite = Int($val)
    Return $__g_RunWaitEx_Default_iConsoleWrite
EndFunc   ;==>_RunWaitEx_DefaultConsoleWrite

Func _RunWaitEx_Last_iPID()
    Return $__g_RunWaitEx_Last_iPID
EndFunc   ;==>_RunWaitEx_Last_iPID

Func _RunWaitEx_Last_hPID()
    Return $__g_RunWaitEx_Last_hPID
EndFunc   ;==>_RunWaitEx_Last_hPID

Func _RunWaitEx_LastStdout($val = Default)
    If $val <> Default Then $__g_RunWaitEx_Last_sStdout = $val
    Return $__g_RunWaitEx_Last_sStdout
EndFunc   ;==>_RunWaitEx_LastStdout

Func _RunWaitEx_LastStderr($val = Default)
    If $val <> Default Then $__g_RunWaitEx_Last_sStderr = $val
    Return $__g_RunWaitEx_Last_sStderr
EndFunc   ;==>_RunWaitEx_LastStderr
Func _RunWaitEx_LastError()
    Return $__g_RunWaitEx_Last_iError
EndFunc   ;==>_RunWaitEx_LastError
Func _RunWaitEx_LastExtended()
    Return $__g_RunWaitEx_Last_iExtended
EndFunc   ;==>_RunWaitEx_LastExtended


; ..say you'd like to change a default due to circumstance
;~ If Not @Compiled Then _RunWaitEx_DefaultShowFlag(@SW_SHOW)

; this example is to showcase the errorlevel/exitcode as the @extended value.
;~      Exit ConsoleWrite('--- Text     >' & _RunWaitEx("dir /.ThisWillFail") & _
;~                        '--- @error   >' & @error & @CRLF & _ ; timeout ?
;~                        '--- exitcode >' & @extended & @CRLF) ; the ErrorLevel returned by the executable

;RunWait: Runs an external program and pauses the script execution until the program finishes, returning the exit code of the program that was run.
;_RunWaitEx: Same as RunWait() but also returns the output text and has an optional timeout.
Func _RunWaitEx($sCommand, $sWorkingDir = Default, $iShowFlag = Default, $iOptFlag = Default, $msTimeout = Default, $iCtrlEdit = Default)
    ;   https://www.autoitscript.com/forum/index.php?showtopic=139260&view=findpost&p=1478119
    ; ------------------- GetExitCodeProcess portion
    Local $hPID_HANDLE, $iExitCode = 0
    Switch $sWorkingDir
        Case "/OpenProcess"
            $hPID_HANDLE = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'int', 0x400, 'int', 0, 'int', $sCommand)
            If Not @error Then Return $hPID_HANDLE
            Return SetError(1, 0, 0)
        Case "/GetExitCodeProcess"
            Local $v_Placeholder, $aRet = DllCall('kernel32.dll', 'ptr', 'GetExitCodeProcess', 'ptr', $sCommand[0], 'int*', $v_Placeholder)
            If Not @error And UBound($aRet) > 2 Then Return $aRet[2]
            Return SetError(1, 0, 0)
        Case "/CloseHandle"
            DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $sCommand)
            If Not @error Then Return 1
            Return 0
    EndSwitch

    ; ------------------- get defaults
    If $sWorkingDir = Default Then $sWorkingDir = _RunWaitEx_DefaultWorkingDir() ; @TempDir
    If $iShowFlag = Default Then $iShowFlag = _RunWaitEx_DefaultShowFlag() ; @SW_HIDE
    If $iOptFlag = Default Then $iOptFlag = _RunWaitEx_DefaultOptFlag() ; "BitOR($STDERR_CHILD, $STDOUT_CHILD) = 6"
    If $msTimeout = Default Then $msTimeout = _RunWaitEx_DefaultTimeout() ; ( 0 ms. = OFF ) in case the process takes longer than expected
    If $iCtrlEdit = Default Then $iCtrlEdit = _RunWaitEx_DefaultCtrlEdit() ; in case a "Console" is needed

    ; ------------------- Run()
    If Not StringInStr($sCommand, @ComSpec) = 1 Then $sCommand = @ComSpec & " /c " & $sCommand
    Local $iPID = Run($sCommand, $sWorkingDir, $iShowFlag, $iOptFlag)
    If @error Or $iPID = 0 Then Return SetError(@error + 100, 0, "")
    $hPID_HANDLE = _RunWaitEx($iPID, "/OpenProcess")
    $__g_RunWaitEx_Last_iPID = $iPID
    $__g_RunWaitEx_Last_hPID = $hPID_HANDLE
    Local $sStr, $hTimer = TimerInit()
    $__g_RunWaitEx_Last_sStdout = ""
    $__g_RunWaitEx_Last_sStderr = ""
    $__g_RunWaitEx_Last_iError = String("")
    $__g_RunWaitEx_Last_iExtended = String("")
    While 1
        $sStr = StdoutRead($iPID)
        If @error Then ExitLoop
        If $msTimeout And TimerDiff($hTimer) > $msTimeout Then ExitLoop
        If $__g_RunWaitEx_Default_iConsoleWrite Then ConsoleWrite($sStr)
        If $iCtrlEdit And $sStr <> "" Then _GUICtrlEdit_AppendText($iCtrlEdit, StringReplace($sStr, @CR, @CRLF) & @CRLF)
        $__g_RunWaitEx_Last_sStdout &= $sStr
        If $__g_RunWaitEx_LoopFuncDo Then $__g_RunWaitEx_LoopFunc($sStr, "")
        If $__g_RunWaitEx_ProcessClose Then ExitLoop
        If $__g_RunWaitEx_DefaultQueueMax > -1 Then $__g_RunWaitEx_Last_sStdout = StringRight($__g_RunWaitEx_Last_sStdout, $__g_RunWaitEx_DefaultQueueMax)
        Sleep(1)
    WEnd
    While 1
        $sStr = StderrRead($iPID)
        If @error Then ExitLoop
        If $msTimeout And TimerDiff($hTimer) > $msTimeout Then ExitLoop
        If $__g_RunWaitEx_Default_iConsoleWrite Then ConsoleWrite($sStr)
        If $iCtrlEdit And $sStr <> "" Then _GUICtrlEdit_AppendText($iCtrlEdit, StringReplace($sStr, @CR, @CRLF) & @CRLF)
        $__g_RunWaitEx_Last_sStderr &= $sStr
        If $__g_RunWaitEx_LoopFuncDo Then $__g_RunWaitEx_LoopFunc("", $sStr)
        If $__g_RunWaitEx_ProcessClose Then ExitLoop
        If $__g_RunWaitEx_DefaultQueueMax > -1 Then $__g_RunWaitEx_Last_sStderr = StringRight($__g_RunWaitEx_Last_sStderr, $__g_RunWaitEx_DefaultQueueMax)
        Sleep(1)
    WEnd
    If $__g_RunWaitEx_ProcessClose Then ProcessClose($iPID)
    If $hPID_HANDLE <> 0 Then
        $iExitCode = _RunWaitEx($hPID_HANDLE, "/GetExitCodeProcess")
        If $iExitCode = 259 Then
            $iExitCode = 100000 + $iPID ; ...process not done, should not close handle.
        Else ;                            ...the PID will be the @extended - 100000
            _RunWaitEx($hPID_HANDLE, "/CloseHandle")
        EndIf
    EndIf
    $__g_RunWaitEx_ProcessClose = 0
    $__g_RunWaitEx_Last_iError = ($msTimeout And TimerDiff($hTimer) > $msTimeout ? 200 : 0)
    $__g_RunWaitEx_Last_iExtended = $iExitCode
    _RunWaitEx_ProcessClose(0) ; just in case the user didn't.
    Return SetError($__g_RunWaitEx_Last_iError, $iExitCode, $__g_RunWaitEx_Last_sStdout & $__g_RunWaitEx_Last_sStderr)
EndFunc   ;==>_RunWaitEx

Func __RunWaitEx_WinAPI_GetClassName($hWnd) ; from <WinAPISysWin.au3> ; internal use
    If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
    Local $aCall = DllCall("user32.dll", "int", "GetClassNameW", "hwnd", $hWnd, "wstr", "", "int", 4096)
    If @error Or Not $aCall[0] Then Return SetError(@error, @extended, '')
    Return SetExtended($aCall[0], $aCall[2])
EndFunc   ;==>__RunWaitEx_WinAPI_GetClassName

 

 

and here is the demo code

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
#AutoIt3Wrapper_Run_Au3Stripper=y
#Au3Stripper_Parameters=/sv /rm
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#cs ----------------------------------------------------------------------------
 AutoIt Version: 3.3.16.1
#ce ----------------------------------------------------------------------------
; Script Start - Add your code below here

#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include "_RunWaitEx.au3" ; https://www.autoitscript.com/forum/topic/212643-_runwaitex-udf/
ConsoleWriteWLineNumber('Version: ' & _RunWaitEx_Version() & @TAB & @error & @TAB & @extended & @CRLF)

;--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
Example_InTheLoop()
Func Example_InTheLoop()
    ConsoleWrite(@CRLF & '+ Example_InTheLoop' & @CRLF & @CRLF)
    ConsoleWriteWLineNumber('DefaultLoopFunc: "' & _RunWaitEx_DefaultLoopFunc() & '"' & @TAB & @error & @TAB & @extended & @CRLF)
    ConsoleWriteWLineNumber('DefaultLoopFunc: "' & _RunWaitEx_DefaultLoopFunc(Example_InTheLoop) & '"' & @TAB & @error & @TAB & @extended & @CRLF)
    ConsoleWriteWLineNumber('DefaultLoopFunc: "' & _RunWaitEx_DefaultLoopFunc() & '"' & @TAB & @error & @TAB & @extended & @CRLF)
    ConsoleWriteWLineNumber('DefaultLoopFunc: "' & _RunWaitEx_DefaultLoopFunc("") & '"' & @TAB & @error & @TAB & @extended & @CRLF)
    ConsoleWriteWLineNumber('DefaultLoopFunc: "' & _RunWaitEx_DefaultLoopFunc() & '"' & @TAB & @error & @TAB & @extended & @CRLF)
    ConsoleWriteWLineNumber('DefaultLoopFunc: "' & _RunWaitEx_DefaultLoopFunc("Example_InTheLoop") & '"' & @TAB & @error & @TAB & @extended & @CRLF)
;~  ConsoleWriteWLineNumber('DefaultLoopFunc: "' & _RunWaitEx_DefaultLoopFunc(DontExtst) & '"' & @TAB & @error & @TAB & @extended & @CRLF)
    ConsoleWriteWLineNumber('DefaultLoopFunc: "' & _RunWaitEx_DefaultLoopFunc(MyLoopOrYours) & '"' & @TAB & @error & @TAB & @extended & @CRLF)
    ConsoleWriteWLineNumber('DefaultLoopFunc: "' & _RunWaitEx_DefaultLoopFunc() & '"' & @TAB & @error & @TAB & @extended & @CRLF)
    _RunWaitEx("Dir")
    _RunWaitEx_DefaultLoopFunc("")
EndFunc   ;==>Example_InTheLoop
Func MyLoopOrYours($WhateverYouMayUseThisFor, $sStringFromCmdLine = "") ; the func needs to have 2 parameters
    #forceref $WhateverYouMayUseThisFor
    ConsoleWriteWLineNumber('' & @MIN & ':' & @SEC & '.' & @MSEC & @TAB & $sStringFromCmdLine & @CRLF)
;~  ProcessClose(_RunWaitEx_Last_iPID())
;~  _RunWaitEx_ProcessClose(1) ; ..remember to set to zero afterwards
EndFunc   ;==>MyLoopOrYours
;--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
Example_InTheEditCtrl()
Func Example_InTheEditCtrl()
    ConsoleWrite(@CRLF & '+ Example_InTheEditCtrl' & @CRLF & @CRLF)
    Local $iW = 600, $iH = 400
    Local $hGUI = GUICreate("Example_InTheEditCtrl", $iW, $iH, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX, $WS_THICKFRAME, $WS_TABSTOP))
    Local $idEdit = GUICtrlCreateEdit("", 0, 0, $iW, $iH)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT + $GUI_DOCKRIGHT + $GUI_DOCKTOP + $GUI_DOCKBOTTOM)
    GUISetState(@SW_SHOW)
    ConsoleWriteWLineNumber('DefaultConsoleWrite: "' & _RunWaitEx_DefaultConsoleWrite() & '"' & @TAB & @error & @TAB & @extended & @CRLF)
    ConsoleWriteWLineNumber('DefaultConsoleWrite: "' & _RunWaitEx_DefaultConsoleWrite(0) & '"' & @TAB & @error & @TAB & @extended & @CRLF)
    ConsoleWriteWLineNumber('DefaultCtrlEdit: "' & _RunWaitEx_DefaultCtrlEdit() & '"' & @TAB & @error & @TAB & @extended & @CRLF)
    ConsoleWriteWLineNumber('DefaultCtrlEdit: "' & _RunWaitEx_DefaultCtrlEdit($idEdit) & '"' & @TAB & @error & @TAB & @extended & @CRLF)
    ConsoleWriteWLineNumber('DefaultCtrlEdit: "' & _RunWaitEx_DefaultCtrlEdit() & '"' & @TAB & @error & @TAB & @extended & @CRLF) ; ..remember to set to zero afterwards
    _RunWaitEx("Dir")
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                GUIDelete($hGUI)
                ExitLoop
        EndSwitch
    WEnd
EndFunc   ;==>Example_InTheEditCtrl
;--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
Func ConsoleWriteWLineNumber($sStr, $iLine = @ScriptLineNumber, $iError = @error, $iExtended = @extended)
    Local $iRet = ConsoleWrite('@@ (' & $iLine & ') : ' & $sStr)
    Return SetError($iError, $iExtended, $iRet)
EndFunc   ;==>ConsoleWriteWLineNumber

so @daledale , please pardon my oops. On the bright side, you may find this ( what I meant ) useful, and hope it serves you in your project :) 

PS: there may be some comments that were true in the original snippet but not longer true/relevant. This is a spur-of-the-moment kind of post.
      Do uncomment and re-comment lines to mess with it, as a learning tool. You're gonna have to read the UDF to know what functions are available ( given my laziness ).

Edited by argumentum
updated to 20250119

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

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
×
×
  • Create New...