Jump to content
Sign in to follow this  
Funtime60

Listening To Multiple Child Process

Recommended Posts

I have a Parent Script that starts multiple, concurrent child processes. I cannot figure out how to apply the technique for using StdoutRead in the examples in a way that listens to them all simultaneously.

For reference, there can be any even number of, or single, child processes and there is an 1D array, $PIDS, that stores the PIDS of all the child processes and they should be outputting to another 1D array $sOutput.

Thank you for your time. Please just point me in the right direction. I'm sorry if I missed another topic that covers this.

Edited by Funtime60
Edit 2: Forgot to add a reason for Edit 1: Grammar

Share this post


Link to post
Share on other sites

Hi,

How to Ask Help

Edited by caramen

My video tutorials : HERE ( In construction )  || My Discord : https://discord.gg/S9AnwHw

How to Ask Help ||  UIAutomation From Junkew || WebDriver From Danp2 || And Water's UDFs in the Quote

Spoiler

 Water's UDFs:
Active Directory (NEW 2018-10-19 - Version 1.4.10.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-10-31 - Version 1.3.4.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Share this post


Link to post
Share on other sites

Could you please be more complete in what you think I missed? I cannot think of anything other than what I tried, which I will add when my laptop can reach the site. I'd like to help anyone who wants to try and assist me with my problem. Thank you.

Edited by Funtime60
Edit 1: wanted to mention that this is from my phone

Share this post


Link to post
Share on other sites

Both StdoutRead and StdinWrite require the PID of the child as the first parameter.  So you just have to poll (read) each of the PIDs to see if the childs have sent you something.  Since StdoutRead is a non-blocking function, there is no issue opting for this strategy.  If you need more detailed help, I would suggest you post a small snippet of both your parent and child in order for us to better understand your problem.

Share this post


Link to post
Share on other sites

I realize that I should have posted code now, which I will do now that it seems my school has unblocked autoitscript.com on the WiFi. Child must be compiled in same directory currently. It must also be named Child1TMP.exe currently. My problem seems to be that my parent keeps trying to pull data even after the children have stopped outputting.

;Snippet of the Parent
Local $x = 100
Local $y = 100
Local $x2 = 100 + $x
Local $y2 = 100 + $y
Local $ChildCount = 4
Local $PIDS[$ChildCount]
Local $PIDSMask = $PIDS
Local $PCount = 0
For $ix = 0 To (2)-1
    For $iy = 0 To (2)-1
        $PIDS[$PCount] = Example($x*$PCount, $y, $x2, $y2)
        $PCount += 1
    Next
Next
For $MCount = 0 To UBound($PIDSMask)-1
    $PIDSMask[$MCount] = 0
Next

Local $sOutput[$ChildCount]
While 1
    For $RCheck = 0 To UBound($PIDS)-1
        If $PIDSMask[$RCheck] =0 Then
            $sOutput[$RCheck] &= StdoutRead($PIDS[$RCheck])
            ConsoleWrite($RCheck&@TAB&StdoutRead($PIDS[$RCheck])&@CRLF) ;Debug
        EndIf
        If @error Then
            $PIDSMask[$RCheck] += 1
            ExitLoop
        EndIf
    Next
WEnd

Func Example($fsx,$fsy,$fdx,$fdy)
    Local $iPID = Run(@ScriptDir&"\Child1TMP.exe", @ScriptDir, @SW_HIDE, 3)

    StdinWrite($iPID, $fsx & @CRLF & $fsy & @CRLF & $fdx & @CRLF & $fdy & @CRLF)

    StdinWrite($iPID)

    Return($iPID)
EndFunc

;Snippet of the Child
Local $sOutput = ""
While True
    $sOutput &= ConsoleRead()
    If @error Then ExitLoop
    Sleep(25)
WEnd

TestWrite($sOutput)

Func TestWrite($input)
    Local $Stuff = StringSplit($input, @CRLF, 1)
    For $x = $Stuff[1] To $Stuff[3]+$Stuff[1]
        For $y = $Stuff[2] To $Stuff[4]+$Stuff[2]
            ConsoleWrite($x&","&$y&@CRLF) ;Output
        Next
    Next
EndFunc

Thank you

Share this post


Link to post
Share on other sites

Your @error should be after the StdOutRead, and not after the EndIf, it will never get an error message that way, the ConsoleWrite resets the error value before you try to read it.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

Like Brew said the @error is misplaced but I also think your dual loop is not working properly.  It should a 3 levels loops.  If you read help file carefully it says : 

StdoutRead() does not block, it will return immediately. In order to get all data, it must be called in a loop.

So in your snippet, you will exitloop before going thru all your childs.  I don't believe this is want you want.  I think you want to exitloop when you reach EOF.

Share this post


Link to post
Share on other sites

I've done something a bit dumb. I've asked you all for help, but now I've gone and changed how my code is intended to function. The only part I think that still applies is this:

4 hours ago, Nine said:

StdoutRead() does not block, it will return immediately. In order to get all data, it must be called in a loop.

I say this because even after looking at the help file, I still have no idea what it means by it "does not block". Am I correct in assuming that this means that the StdoutRead()  won't be able to pull anything after the process closes?

I'll post an updated snippet when I finish the changes.

Edited by Funtime60

Share this post


Link to post
Share on other sites
33 minutes ago, Funtime60 said:

Am I correct in assuming that this means that the StdoutRead()  won't be able to pull anything after the process closes?

No, it means that using the function, it  will not stop the script at that function.  It will continue returning a value that says something it has nothing to read.  Unlike for example a msgbox () which ofc is totally different, it will block the script till the user respond to the message...

Edit : for everyone who will read this.  When you look at the help file and you do not understand a sentence, you should know that you are missing something important.  All single words in this help file are truly essential. Read carefully multiple times the help subject, try the examples, modify the examples at the places you are unsure of the meaning.  This is the best recommandation I can give...

Edited by Nine

Share this post


Link to post
Share on other sites

Hi @Funtime60, at first glance on your listing I see 2 inaccuracies quite macroscopic .

  1. One is that you try to read twice the same data from the StdOut straem buffer. Once you read  the I/O stream from your process, that stream buffer is emptyed, so next read will get data only if new data is present, otherwyse you get an empty string (and not an @error). Of course the first stdoutread, stores the read data in the  $sOutput[$RCheck] variable, so you have to use that variable to 'see' and manage data read.
  2. two, as already pointed out by BrewManNH and Nine, the  @error macro is misplaced. In short the use of the @error macro to check if a process has finished, it should be placed right after the StdOutread statement, so if the @error is set to true it means that the Pid you are trying to read doesn't exists anymore, tht is, it has finished and closed himself. (you can still read data from the stdoutread buffer even if in some cases I got issues in that way). Another maybe more kind way to check if a process has finished is to use the ProcessExist() function.

Here your script a little modified (quick and dirty) should do what you expect (at least I hope...)
P.S. maybe you can also be interested to this link where there is a ready made way to run and manage many external process.

;Snippet of the Parent
Local $x = 100
Local $y = 100
Local $x2 = 100 + $x
Local $y2 = 100 + $y
Local $ChildCount = 4
Local $PIDS[$ChildCount]
Local $PIDSMask = $PIDS
Local $PCount = 0
For $ix = 0 To(2) - 1
    For $iy = 0 To(2) - 1
        $PIDS[$PCount] = Example($x * $PCount, $y, $x2, $y2)
        $PCount += 1
    Next
Next
For $MCount = 0 To UBound($PIDSMask) - 1
    $PIDSMask[$MCount] = 0
Next

Local $sOutput[$ChildCount], $TasksDone = 0
; While 1
Do
    $TasksDone = 0
    For $RCheck = 0 To UBound($PIDS) - 1

        ; If $PIDSMask[$RCheck] =0 Then
        $CheckData = StdoutRead($PIDS[$RCheck]) ; check presence of new data on the $PID's stream
        If $CheckData <> "" Then ; if we got something then keep it
            $sOutput[$RCheck] &= $CheckData ; stack task's stdout
            ; ConsoleWrite($RCheck&@TAB&StdoutRead($PIDS[$RCheck])&@CRLF) ; StdOut already read!!, you con't read twice same data
            ConsoleWrite($RCheck & @TAB & $sOutput[$RCheck] & @CRLF) ;Debug ; print already got data to console
        EndIf
        ; EndIf
        ; If @error Then
        If Not ProcessExists($PIDS[$RCheck]) Then
            $TasksDone += 1
            ; $PIDSMask[$RCheck] += 1
            ; ExitLoop
        EndIf
    Next
Until $TasksDone = UBound($PIDS)
; WEnd

Func Example($fsx, $fsy, $fdx, $fdy)
    Local $iPID = Run(@ScriptDir & "\Child1TMP.exe", @ScriptDir, @SW_HIDE, 3)

    StdinWrite($iPID, $fsx & @CRLF & $fsy & @CRLF & $fdx & @CRLF & $fdy & @CRLF)

    StdinWrite($iPID)

    Return($iPID)
EndFunc   ;==>Example

#cs
    ;Snippet of the Child
    Local $sOutput = ""
    While True
    $sOutput &= ConsoleRead()
    If @error Then ExitLoop
    Sleep(25)
    WEnd
    
    TestWrite($sOutput)
    
    Func TestWrite($input)
    Local $Stuff = StringSplit($input, @CRLF, 1)
    For $x = $Stuff[1] To $Stuff[3] + $Stuff[1]
    For $y = $Stuff[2] To $Stuff[4] + $Stuff[2]
    ConsoleWrite($x & "," & $y & @CRLF) ;Output
    Next
    Next
    EndFunc   ;==>TestWrite
#ce

 


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

Chimp definitely solved it for me. I'm sorry if I missed someone else's solution. Thanks everyone for helping me understand the issue.

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  

  • Similar Content

    • By GillesMaisonneuve
      Good morning,
       
      I am trying to read a Unicode utf8 string from a perl subprocess via StdoutRead.
      I use an AUtoIt GUI and display result in an 'Edit' control (see my code below) using 'Courier New', a font that can handle Unicode characters.
      I was expecting a result looking like (CMD console):
      ++$ chcp 65001>NUL: & perl -Mutf8 -CS -e "use 5.018; binmode STDOUT,q(:utf8); say qq(\x{03A9})" & chcp 850>NUL: Ω Instead I get someting like this (see downward the screen copy):
      ++$ chcp 1250>NUL: & perl -Mutf8 -CS -e "use 5.018; binmode STDOUT,q(:utf8); say qq(\x{03A9})" & chcp 850>NUL: Ω Obviously while I was expecting to receive an utf8 char, it seems to have been converted to Windows ANSI codepage 1250 (Windows default for Western/Central Europe, right ?)
      What am I doing wrong? Is there someone who could guide me?
       
      Here is my code and my output in the GUI.
      Creating and configuring the Edit control:
      Local $Edit1 = GUICtrlCreateEdit( "", 20, 110, 780, 500, BitOr($GUI_SS_DEFAULT_EDIT,$ES_MULTILINE,$ES_READONLY) ) GUICtrlSetData($Edit1, "This field will contain text result from external Perl command") GUICtrlSetFont($Edit1, 10, $FW_THIN, $GUI_FONTNORMAL, "Courier New")  
      Executing Perl command (note: `-Mutf8` and `-CS` garantees that I work in utf8 and STDOUT accepts wide-characters):
      local $ExePath = 'perl.exe -Mutf8 -CS ' ;~ if perl in PATH, no need for full path C:\Perl\bin\perl.exe local $Params = '-e "use 5.018; use utf8; use charnames q(:full); binmode STDOUT,q(:utf8);' & _ 'say scalar localtime; say qq(\N{GREEK CAPITAL LETTER OMEGA})"' local $Cmd = $ExePath & ' ' & $Params Local $iPID = Run($Cmd, "", @SW_HIDE, BitOR($STDERR_CHILD, $STDOUT_CHILD))  
      Reading STDOUT and displaying it into the Edit control:
      While 1 $sOutput &= StdoutRead($iPID) If @error Then ; Exit the loop if the process closes or StdoutRead returns an error. ExitLoop EndIf WEnd If $sOutput <> '' Then GUICtrlSetData($Edit1, $sOutput) EndIf  
      And now, what I get on my GUI:
       

    • By Blueman
      Hey Guys,

      I have a (i think) simple question, but i can't seem to get the answer though the help-files.
      Hope that you can help me with this issue.
      - I am opening a SSH Connection with the following function
      Func _Connect($session,$usr,$pass) $exec = @ScriptDir & "\PLINK.EXE" If Not FileExists($exec) Then _Err("PLINK.EXE Not Found!",0) $pid = Run($exec & " -load " & $session & " -l " & $usr & " -pw " & $pass, @ScriptDir, @SW_HIDE, 0x1 + 0x8) ;Run SSH.EXE If Not $pid Then _Err("Failed to connect",0) $currentpid = $pid ;$rtn = _Read($pid) ;Check for Login Success - Prompt ;MsgBox(48,"","1") ;sleep(5000) ;Wait for connection Return $pid EndFunc - This will connect to a CMS Server with a vt100 interface where a dynamic report is generated every 20 seconds.
      - Then i will read the contents with the following Function
      Func _Read($pid) $SSHREADTIMEOUT = 0 If Not $pid Then Return -1 Local $dataA Local $dataB Do $SSHREADTIMEOUT += 1 $dataB = $dataA sleep(100) $dataA &= StdOutRead($pid) If @error Then ExitLoop Until ($dataB = $dataA And $dataA And $dataB) OR $SSHREADTIMEOUT == 50 Return $dataA EndFunc This all goes correctly, but i can only read the contents once.
      When i try to read the contents again i get nothing.
      Maybe because the CMS isn't changing, but the values in the report is changing every 20 seconds.
      I need to somehow read al of the contents every time i perform a Read action, but how?
      Yes, i can use it in a While loop, but also then i get nothing or a small line of text and not the whole report.
       
      Any Idea?
       
      Thanks Guys!
       
      --Edit--
      I have fixed the problem by changing the terminal session to a vt220 session.
      The only problem now is that i want to send the: "Data link escape" command and that is something i cannot fix,.
      I have tried;
      StdinWrite($Pid,Hex(0x10)) StdinWrite($Pid,Chr(16)) StdinWrite($Pid,{DLE}) But nothing seems to work.  
      -- Edit-2 --
      Guys, fixed that too!
      Forgot to add the number '5' to actually execute the assignment.
      So fixed it by using;
       
      StdinWrite($Pid,Chr(16)) StdinWrite($Pid,"5")
      Thanks for reading with me
       
    • By rudi
      Hello,
      to provide an easy to use starter to capture traffic on all NICs found, I can successfully get all the interfaces of TSHARK.EXE (the command line version that's automatically installed along with wireshark) with this script:
      #include <AutoItConstants.au3> #include <Array.au3> $TS_WD = "C:\Program Files\Wireshark" $TS_exe = $TS_WD & "\tshark.exe" if not FileExists($TS_exe) Then MsgBox(48,"Fatal Error","No Wireshark Commandline Tool ""TSHARK.EXE"" found:" & @CRLF & _ $TS_exe) Exit EndIf $DString = "" $PIDGetIFs = Run($TS_exe & " -D", $TS_WD, @SW_HIDE, $STDERR_MERGED) While ProcessExists($PIDGetIFs) $DString &= StdoutRead($PIDGetIFs) WEnd ; MsgBox(0,"IFs",$DString) $aNICs = StringSplit($DString, @CRLF, 1) _ArrayDisplay($aNICs) $RegExIF = "^(?:\d+\. )(\\.*?})(?: \()(.*?)(\))$" ; $1 = TSHARK Interface Name, $2 = Windows Interface Name ; ... get the names to run TSHARK with the appropriate interface string  
      When I run TSHARK.EXE using this line directly, I see a continuously growing number telling the number of packets captured so far.
      "C:\Program Files\Wireshark\tshark.exe" -i \Device\NPF_{AEB931E9-E5FA-4DA5-8328-D87BDF53805C} -b duration:300 -b files:600 -w "y:\TShark-Ringbuffer\LAN-Verbindung\TSHARK-Com-0317_17---LAN-Verbindung___.pcap" Using this script, I *DO* see the first output line "Capturing on 'LAN-Verbindung'", but I cannot get hold of the continuously growing number of packets captured so far.
      #include <AutoItConstants.au3> $WD="C:\Program Files\Wireshark" $CMD='"C:\Program Files\Wireshark\tshark.exe" -i \Device\NPF_{AEB931E9-E5FA-4DA5-8328-D87BDF53805C} -b duration:300 -b files:600 -w "y:\TShark-Ringbuffer\LAN-Verbindung\TSHARK-Com-0317_17---LAN-Verbindung___.pcap"' ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $CMD = ' & $CMD & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $PID=Run($CMD,$WD,@SW_SHOW,$stderr_merged) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $PID = ' & $PID & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $OutputAll="" While ProcessExists($PID) $output=StdoutRead($PID) $OutputAll&=$output ToolTip($OutputAll) if $output <> "" then ConsoleWrite("""" & $output & """" & @CRLF) Sleep(1000) WEnd ConsoleWrite("Process vanished" & @CRLF)  
      This is the output of SciTE, when I let TSHARK.EXE run for a short while, the "close" it's "box" ...
       
      --> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop @@ Debug(10) : $CMD = "C:\Program Files\Wireshark\tshark.exe" -i \Device\NPF_{AEB931E9-E5FA-4DA5-8328-D87BDF53805C} -b duration:300 -b files:600 -w "y:\TShark-Ringbuffer\LAN-Verbindung\TSHARK-Com-0317_17---LAN-Verbindung___.pcap" >Error code: 0 @@ Debug(13) : $PID = 10948 >Error code: 0 "Capturing on 'LAN-Verbindung' " Process vanished  
      Howto catch the "growing-packet-number" TSHARK.EXE is writing continuously to the same "window position"???
       
       
      Regards, Rudi.
       


    • By ModemJunki
      OK, the odd stuff seems to happen to me. Not sure if this belongs here or in the deployment forum.
      The Question: Why would the console output results from a command-line tool need to know the working dir on one system but not the other?
      Though in the end I solved the issue I still am not understanding why StdoutRead seems to behave differently as I describe below.
      Preamble: Windows 10 image deployment to two different HP workstation hardware platforms. After deployment set up some disk space using Intel RAID. I script the Intel RSTe client (Intel® Rapid Storage Technology enterprise). Same version of the RSTe client and same storage controller hardware (Intel C600+/C220+ series chipset SATA RAID controller). The only difference is in the driver - one system has 4.2.0.1136 and the other has 5.2.0.1194, but even after I update the older driver the anomaly persists. There are of course other differences - the older system has different CPUs (Xeon E5-2620 vs Xeon Silver 4108), different chipsets, different SMBIOS, etc..). Both have Nvidia Quadro cards with driver 385.90, but the older has 3x P2000 cards and the newer has 3x Quadro M4000 and a Quadro K1200.
      To script RAID creation and maintenance I have a function that uses StdoutRead with Intels command line client tool "rstcli64.exe".
      On the older system, the below call to StdoutRead fails. On the newer system, it works. This only started happening on the older hardware when I updated the Windows version 1607 image to build 14393.2189 (but the Windows image used is the same for both hardware targets).
      $s_DoRST = Run(@ComSpec & " /c " & $s_RSTcmd, "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD) But if I change it to use @ScriptDir as the working dir, it works for both systems.
      $s_DoRST = Run(@ComSpec & " /c " & $s_RSTcmd, @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)  The code below is the one that works on both systems (hint: the comment " ; this only deals with one device" is because I've no hardware with more than one ATAPI device to test with).
      $s_RSTExe = ".\rstcli64.exe" ; for production (compiled executable) ; #FUNCTION# ==================================================================================================================== ; Name ..........: GetDiskInfoFromRSTE() ; Description ...: Queries for hard disks attached to the controller ; Syntax ........: GetDiskInfoFromRSTE() ; Parameters ....: None ; Return value...: An array of attached hard disk datas from the RST command line tool without ATAPI devices such as optical drives ; =============================================================================================================================== Func _GetDiskInfoFromRSTE() Local $s_RSTcmd = $s_RSTExe & " -I -d" Local $s_DoRST, $a_RSTDisksTemp, $s_rawdata, $numDISK = 0 If $Debug <> 0 Then ConsoleWrite("Get disk info: " & $s_RSTcmd & @CRLF) ; useful during dev but cannot be used if #requireadmin $s_DoRST = Run(@ComSpec & " /c " & $s_RSTcmd, @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD) ProcessWaitClose($s_DoRST) $s_rawdata = StdoutRead($s_DoRST) $a_RSTDisksTemp = StringSplit($s_rawdata, @CRLF) For $i = $a_RSTDisksTemp[0] To 1 Step -1 ; since we are deleting items, we have to go backwards through the array If $a_RSTDisksTemp[$i] = "" Or $a_RSTDisksTemp[$i] = "--DISK INFORMATION--" Then _ArrayDelete($a_RSTDisksTemp, $i) EndIf Next $a_RSTDisksTemp[0] = UBound($a_RSTDisksTemp) If IsArray($a_RSTDisksTemp) Then For $j = $a_RSTDisksTemp[0] - 1 To 1 Step -1 ; we need to remove the ATAPI device(s), since we delete we have to step through in reverse If StringInStr($a_RSTDisksTemp[$j], "Disk Type: SATA") Then $numDISK = $numDISK + 1 EndIf Next For $j = $a_RSTDisksTemp[0] - 1 To 1 Step -1 ; we need to remove the ATAPI device(s), since we delete we have to step through in reverse If StringInStr($a_RSTDisksTemp[$j], "ATAPI") Then ; we have to delete the ID entry BEFORE and AFTER the ATAPI entry to remove the ATAPI device (always delete from the bottom up!). _ArrayDelete($a_RSTDisksTemp, $j + 1) ; delete entry below _ArrayDelete($a_RSTDisksTemp, $j) ; delete entry _ArrayDelete($a_RSTDisksTemp, $j - 1) ; delete entry above ExitLoop ; this only deals with one device. If there were more we would need to capture all ATAPI device ID locations into another array then delete the original array entries based on the index numbers in the new array. EndIf Next $a_RSTDisksTemp[0] = UBound($a_RSTDisksTemp) If $a_RSTDisksTemp[0] <> 1 Then If $Debug <> 0 Then ConsoleWrite("Found " & $numDISK & " disk(s) attached to controller." & @CRLF) _infoLog("_GetDiskInfoFromRSTE() found " & $numDISK & " disk(s) attached to controller.", $msgSource) Else If $Debug <> 0 Then ConsoleWrite("No disks found to be attached to controller." & @CRLF) _infoLog("No disks found to be attached to controller.", $msgSource) EndIf Else If $Debug <> 0 Then ConsoleWrite("Unable to query RAID controller. Check hardware and version of RST client software." & @CRLF) _errorLog("Unable to query RAID controller. Check hardware.", $msgSource) Exit EndIf Return $a_RSTDisksTemp EndFunc ;==>_GetDiskInfoFromRSTE  
    • By OGA
      Hi, I'm new.
      Anyways, I'm using the RunBinary.au3 script by trancexx and I want to re-direct the STDOUT of the "child process" back to the autoit script that launches it. I'm attempting to do so using named pipes. If its possible to use StdoutRead instead of namedpipes please let me know. I'm just unsure of how to provide a handle of the childs STDOUT stream to that function. Though DllCall("kernel32.dll", "ptr", "GetStdHandle", "dword", "STD_OUTPUT_HANDLE") seems to get the handle?
      Please excuse any foolish mistakes because I'm new to STDOUT, runbinary and namedpipes. Here's the parts of the code I'm trying to use that are relevent:
      ;~~~Firstly I think I need to make a pipe that's inheritable.. which I may have done wrong Local $_SECURITY_ATTRIBUTES = DllStructCreate("dword Length;" & _ "int lpSecurityDescriptor;" & _ "bool InheritHandle;") ;***Not positive if bool works correctly here? DLLStructSetData($_SECURITY_ATTRIBUTES, "Length", DllStructGetSize($_SECURITY_ATTRIBUTES)) DLLStructSetData($_SECURITY_ATTRIBUTES, "lpSecurityDescriptor", 0) ;***This sets default state; "If the value of this member is NULL, the object is assigned the default security descriptor associated with the access token of the calling process." but I'm unsure if this is what I should use DLLStructSetData($_SECURITY_ATTRIBUTES, "InheritHandle", true);***True = Inheritable(but again I'm not positive the bool works correctly?) Global $hNamedPipe = _NamedPipes_CreateNamedPipe("\\.\pipe\poopp", _;Name 2, _;Direction: 2=both ;I only need 1 direction but I'm just using this for testing 1, _;Flags: 1=no extra instances of pipe are allowed to run 0, _;Security: No ACL Security 0, _;Type: 0=byte 0, _;ReadType: 0=byte 1, _;Wait: 0=Block(wait) 1=No block(no wait) 1, _;Max Instances of pipe allowed 4096, _;out size 4096, _;in size 9000, _;timeout DllStructGetPtr($_SECURITY_ATTRIBUTES));Default=0 which wouldn't make the handle inheritable ;~~~Next I would need to set the STARTUPINFO of the process ;code used by trancexx for the _STARTUPINFO Global $tSTARTUPINFO = DllStructCreate("dword cbSize;" & _ "ptr Reserved;" & _ "ptr Desktop;" & _ "ptr Title;" & _ "dword X;" & _ "dword Y;" & _ "dword XSize;" & _ "dword YSize;" & _ "dword XCountChars;" & _ "dword YCountChars;" & _ "dword FillAttribute;" & _ "dword Flags;" & _ "word ShowWindow;" & _ "word Reserved2;" & _ "ptr Reserved2;" & _ "ptr hStdInput;" & _ "ptr hStdOutput;" & _ "ptr hStdError") ;Attempting to set the values for namedpipe redirection DllStructSetData($tSTARTUPINFO, "Flags", 0x00000100) ;***Flag = STARTF_USESTDHANDLES (I think I set it correctly?) DllStructSetData($tSTARTUPINFO, "hStdOutput", $hNamedPipe) ;***Currently setting the output handle to the SERVER end of the NamePipe I'm creating (which I'm pretty sure is wrong but idk how to use the Client End) ;~~~code used by trancexx for CreateProcess Global $aCall = DllCall("kernel32.dll", "bool", "CreateProcessW", _ "wstr", $sExeModule, _ "wstr", $sCommandLine, _ "ptr", 0, _ "ptr", 0, _ "bool", true, _ ;***changed to inherit handles (not positive I did so correctly) was int 0 before "dword", 4, _ ; CREATE_SUSPENDED ; <- this is essential "ptr", 0, _ "ptr", 0, _ "ptr", DllStructGetPtr($tSTARTUPINFO), _ "ptr", DllStructGetPtr($tPROCESS_INFORMATION)) ;~~~~~Code used in a loop to try to see if anything is being written into the pipe If _IsPressed(35, $hDLL) Then Local $pipeData = _NamedPipes_PeekNamedPipe($hNamedPipe) If @Error Then MsgBox(1,"PipeData Error",@Error & " | " & $pipeData) Else Local $r = _ArrayDisplay($pipeData) If @Error Then MsgBox(1,"Array Error",@Error & " | " & $pipeData) EndIf EndIf  
      I'm not using this exact code cause I changed it around some for the post. I'm mainly wondering how to correctly use the client end of the name pipe? I also had some values I wasn't sure if I set correctly because I don't have experience with com objects. And It seems the process launched needs to be the child?.. Can the process started through the autoitscript can be considered the child process and the script the parent process?
       
      Guides I'm using for this:
      https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
      https://support.microsoft.com/en-us/help/190351/how-to-spawn-console-processes-with-redirected-standard-handles
×
×
  • Create New...