Jump to content
Sign in to follow this  
TheFluffyOne

Retrieving STDOUT *and* return code from spawned process

Recommended Posts

TheFluffyOne

I have some VBScripts that I wish to launch from a deployment tool that will only run BAT, CMD, and EXE files. Having seen AutoIt's ability to convert scripts to EXEs it seems the ideal way to solve my problem without resorting to a lower-level language.

So I've created an AutoIt script that launches cscript.exe with the script name as a parameter and at a basic level this works. Using RunWait I was able to launch the scripts and check the return code (passing this out to the deployment tool so it knew if the task was successful or not).

Unfortunately all of my debug information goes to STDOUT/STDERR and when using RunWait this appears to be routed to a black hole by default. I switched to using Run so that I can read the debug info and pass it back out to the calling app, and this works just fine. Except there now doesn't seem to be a way to read the return code muttley

So can I have my cake and eat it? Can I spawn a process, read its STDOUT/STDERR streams, *and* check its return code using AutoIt?

Share this post


Link to post
Share on other sites
ProgAndy

You have to create the process yourself and maka all on your own:

Tried to change example from http://www.autoitscript.com/forum/index.ph...st&p=467590

#include <NamedPipes.au3>
#include <WinAPI.au3>
#include <Constants.au3>


; ====================================================================================================
;~ ===========================
; Description ...: Shows how to use pipe functions to read the output from a console operation
; Author ........: Paul Campbell (PaulIA)
; Notes .........: This script MUST be run in SciTE in order to see the results
; ====================================================================================================
;~ ===========================

; ====================================================================================================
;~ ===========================
; Main
; ====================================================================================================
;~ ===========================
ConsoleWrite("---- Executing Program" & @CRLF)
$data = _RunWaitStdOut("cmd.exe /c dir c:\windows","",@SW_HIDE)
$exitCode = @extended
ConsoleWrite("-> Return Code: " & $exitCode & @CRLF)
ConsoleWrite("> StdOut+StdErr: " & @CRLF)
ConsoleWrite($data & @CRLF)

;ExecuteCmd("ping www.autoit.com")

; ====================================================================================================
;~ ===========================
; Execute a command and display the results
; ====================================================================================================
;~ ===========================
Func _RunWaitStdOut($sCmd, $sWorkingDir = "", $state = @SW_SHOW)
   Local $iBytes, $sData, $hReadPipe, $hWritePipe, $tBuffer, $tProcess, $tSecurity, $tStartup
   Local $STILL_ACTIVE = 0x103
   Local Const $STARTF_USESHOWWINDOW = 0x1
   Local Const $STARTF_USESTDHANDLES = 0x100

   ; Set up security attributes
   $tSecurity = DllStructCreate($tagSECURITY_ATTRIBUTES)
   DllStructSetData($tSecurity, "Length", DllStructGetSize($tSecurity))
   DllStructSetData($tSecurity, "InheritHandle", True)

   ; Create a pipe for the child process's STDOUT
   _NamedPipes_CreatePipe($hReadPipe, $hWritePipe, $tSecurity)

   ; Create child process
   $tProcess = DllStructCreate($tagPROCESS_INFORMATION)
   $tStartup = DllStructCreate($tagSTARTUPINFO)
   DllStructSetData($tStartup, "Size", DllStructGetSize($tStartup))
   DllStructSetData($tStartup, "Flags", BitOR($STARTF_USESTDHANDLES, $STARTF_USESHOWWINDOW))
   DllStructSetData($tStartup, "StdOutput", $hWritePipe)
   DllStructSetData($tStartup, "StdError", $hWritePipe)
   DllStructSetData($tStartup, "ShowWindow", $state)
   _WinAPI_CreateProcess("", $sCmd, 0, 0, True, 0, 0, $sWorkingDir, DllStructGetPtr($tStartup), DllStructGetPtr($tProcess))
   Local $handle = DllStructGetData($tProcess, "hProcess")

   _WinAPI_CloseHandle(DllStructGetData($tProcess, "hThread"))
   Local $kernel = DllOpen("kernel32.dll"), $exitCode
   Do
      $exitCode = DllCall($kernel, "long", "GetExitCodeProcess", "hwnd", $handle, "dword*", 0)
   Until $exitCode[0] <> $STILL_ACTIVE
   $exitCode = $exitCode[2]
   ; Close the write end of the pipe before reading from the read end of the pipe
   _WinAPI_CloseHandle($handle)
   _WinAPI_CloseHandle($hWritePipe)
   ; Read data from the child process
   $tBuffer = DllStructCreate("char Text[4096]")
   While 1
      _WinAPI_ReadFile($hReadPipe, DllStructGetPtr($tBuffer), 4096, $iBytes)
      If $iBytes = 0 Then ExitLoop
      $sData &= StringLeft(DllStructGetData($tBuffer, "Text"), $iBytes)
   WEnd
   _WinAPI_CloseHandle($hReadPipe)
   SetExtended($exitCode)
   Return $sData
EndFunc   ;==>_RunWaitStdOut
Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites
Squirrely1

If you use SciTe, I think you can save a file as .au3 and with this text "StdoutRead" selected, hit the F1 function key and the help file should open to help on this topic - read the example on the bottom of the page newbie, and welcome to the AutoIt forums.

If you think your VBScript files are in good shape and can do what you want them to do, you can test them from a .bat file with these lines of code in it:

"C:\My Documents\myscript01.vbs"
"C:\My Documents\myscript02.vbs"

To launch them from AutoIt, compiled or otherwise:

ShellExecuteWait("C:\My Documents\myscript01.vbs")
ShellExecuteWait("C:\My Documents\myscript02.vbs")

Das Häschen benutzt Radar

Share this post


Link to post
Share on other sites
ProgAndy

He wants StdOut AND ExitCode , that isn't possible with standard AutoIt, but the above should work muttley


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites
TheFluffyOne

You have to create the process yourself and maka all on your own:

... code example snipped...

Thanks ProgAndy. I'm surprised it needs that much work, but that code should do the job. Cheers!

Share this post


Link to post
Share on other sites
TheFluffyOne

If you use SciTe, I think you can save a file as .au3 and with this text "StdoutRead" selected, hit the F1 function key and the help file should open to help on this topic - read the example on the bottom of the page newbie, and welcome to the AutoIt forums.

Thanks for the reply, and the welcome :)

As mentioned in my original post, I was able to get the STDOUT/STDERR information when using Run. The issue is that the RunWait function doesn't allow me to read the standard output streams and that Run doesn't let me read the return code. I had already checked the help file under Run, RunWait, StdOutRead, and StdErrRead and couldn't see a way to achieve what I wanted. The code posted by ProgAndy looks to be the (slightly complex) solution muttley

Share this post


Link to post
Share on other sites
ProgAndy

The Code is complex, because it does everything manually, what normally is done by AutoIt itself. Propably you should open a featurerequest for RunWait with StdOut Option muttley


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
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
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.