Sign in to follow this  
Followers 0
gritts

Sending control characters to DOS command started with script

7 posts in this topic

I have been wracking my brains today trying to figure out how to send a control character to a DOS command I initiate within a script. I am doing this little project to eventually add a GUI to some older DOS based apps still in use. (Not everyone appreciates the fine art of command line execution I guess  :P ) Anywho, to test my scripting and what I was able to dig up, I came up with the following. (Yes, I know AutoIT has a ping function, DOS ping was what I came up with to test sending commands to, it is not the final program)

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.12.0
 Author:         myName

 Script Function:
    Template AutoIt script.

#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here


#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>
#include <process.au3>
Opt("GUIOnEventMode", 1)
#Region ### START Koda GUI section ###
$Main = GUICreate("Ping Now", 547, 62, 192, 124)
GUISetFont(10, 400, 0, "MS Sans Serif")
GUISetOnEvent($GUI_EVENT_CLOSE, "MainClose")
GUISetOnEvent($GUI_EVENT_MINIMIZE, "MainMinimize")
GUISetOnEvent($GUI_EVENT_MAXIMIZE, "MainMaximize")
GUISetOnEvent($GUI_EVENT_RESTORE, "MainRestore")
$tbPingURL = GUICtrlCreateInput("", 16, 16, 425, 24)
GUICtrlSetOnEvent($tbPingURL, "tbPingURLChange")
$btnPingStart = GUICtrlCreateButton("Ping Now", 456, 16, 75, 25)
GUICtrlSetOnEvent($btnPingStart, "btnPingStartClick")
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
Global $srPID

While 1
    Sleep(100)
WEnd

Func btnPingStartClick()
    Local $sURL = GUICtrlRead($tbpingURL),$stdOutLine
    MsgBox(0,"Ping URL","Reading URL: "&$sURL) ;ignored as I got tired of typing
    $srPID = Run(@ComSpec&" /c "&"ping -t yahoo.com","",@SW_HIDE,$STDIN_CHILD + $STDOUT_CHILD)
    ConsoleWrite("Running with PID: "&$srPID&@CRLF)
Sleep(1000)

EndFunc
Func MainClose()
    ;ControlSend(@ComSpec,"","",Chr(3),1)
    ;ConsoleWrite(_ProcessGetName($srPID))
    $charout=StdinWrite($srPID,Chr(3))
    ConsoleWrite($charout&"  -  "&@error&@CRLF)
    StdinWrite($srPID)
    ;ProcessWait($srPID)
    ProcessWaitClose($srPID)
    Exit
EndFunc
Func MainMaximize()

EndFunc
Func MainMinimize()

EndFunc
Func MainRestore()

EndFunc
Func tbPingURLChange()

EndFunc

When I close the resulting window, I am expecting a CTRL+c to be sent to the running Ping command. Instead, I get a result code back implying that the command was send but nothing happens after that. Ping continues to run in the background till I end its process through Task Manager. When I end the process, the script closes, provided I attempt to close the GUI window (Func MainClose()). If I do not try to close the GUI first and end the ping process through task manager, I get a '0' as the result code for StdInWrite.

The PID returned is NOT that of the child process initiated by the Run command but that of the cmd.exe that is started to run the Ping command within. Leaving off the @comspec portion of the Run statement makes no difference, the ping continues to run till ended. 

Any suggestions? I noted that other queries about sending control keys to DOS commands have been posted in the past but I didn't really pick up on a solution.

Share this post


Link to post
Share on other sites



Any suggestions? I prefer no to just end the process as the normal means to close the application is with a "CRTL+c" keypress.

Share this post


Link to post
Share on other sites

Well, I'm not sure to really understand what is your problem...

Does this code helps you ?

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.12.0
 Author:         myName

 Script Function:
    Template AutoIt script.

#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here


#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>
#include <process.au3>
Opt("GUIOnEventMode", 1)
#Region ### START Koda GUI section ###
$Main = GUICreate("Ping Now", 547, 62, 192, 124)
GUISetFont(10, 400, 0, "MS Sans Serif")
GUISetOnEvent($GUI_EVENT_CLOSE, "MainClose")
GUISetOnEvent($GUI_EVENT_MINIMIZE, "MainMinimize")
GUISetOnEvent($GUI_EVENT_MAXIMIZE, "MainMaximize")
GUISetOnEvent($GUI_EVENT_RESTORE, "MainRestore")
$tbPingURL = GUICtrlCreateInput("", 16, 16, 425, 24)
GUICtrlSetOnEvent($tbPingURL, "tbPingURLChange")
$btnPingStart = GUICtrlCreateButton("Ping Now", 456, 16, 75, 25)
GUICtrlSetOnEvent($btnPingStart, "btnPingStartClick")
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
Global $srPID

While 1
    Sleep(100)
WEnd

Func btnPingStartClick()
    Local $sURL = GUICtrlRead($tbpingURL),$stdOutLine
    MsgBox(0,"Ping URL","Reading URL: "&$sURL) ;ignored as I got tired of typing
    $srPID = Run(@ComSpec&" /c ping -t google.com","","",$STDIN_CHILD + $STDOUT_CHILD)
    ConsoleWrite("Running with PID: "&$srPID&@CRLF)
EndFunc


Func MainClose()
    ProcessClose($srPID)
    
    $sOutput = StdoutRead($srPID)
    ConsoleWrite($sOutput)
    
    Exit
EndFunc

Func MainMaximize()

EndFunc
Func MainMinimize()

EndFunc
Func MainRestore()

EndFunc
Func tbPingURLChange()

EndFunc

Share this post


Link to post
Share on other sites

The problem is that Ping with the "-t" parm pings the target continuously until a CTRL+C is received by the command window.  It seems that "normal" methods do not work on the command window.  Do a Google search for lot's of info on it.


Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites

@jguinch - Your approach does work and I can use it. I had tested it in a version of my script but I am trying to exhaust my options first before I just kill the process. The process I intend to use this with likes to be closed with a CTRL+c but it can be killed. It closes connections and files when it receives the CTRL+c. I used ping as it seemed the best proxy for the actual programs. I hope to use this method against a proprietary app in our office as a means of creating an eventual front-end of sorts. 

@kylomas - I did reseach Google for a while and after feeling like I was running in circles I came to the same conclusion. I had read here that others were attempting the same if not similar things I was attempting (CTRL+c to a console window opened with the "Run" command) but did not see where there had been a resolution. (Unless my search criteria never returned the results)

It almost sounds like sending the CTRL+c is not possible. I'll keep plugging away at it... 

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

@jguinch - Your approach does work and I can use it. I had tested it in a version of my script but I am trying to exhaust my options first before I just kill the process. The process I intend to use this with likes to be closed with a CTRL+c but it can be killed. It closes connections and files when it receives the CTRL+c. I used ping as it seemed the best proxy for the actual programs. I hope to use this method against a proprietary app in our office as a means of creating an eventual front-end of sorts. 

@kylomas - I did reseach Google for a while and after feeling like I was running in circles I came to the same conclusion. I had read here that others were attempting the same if not similar things I was attempting (CTRL+c to a console window opened with the "Run" command) but did not see where there had been a resolution. (Unless my search criteria never returned the results)

It almost sounds like sending the CTRL+c is not possible. I'll keep plugging away at it... 

 

Any luck? I've searched for the past hour, Writing Chr(3) to StdIn nor GenerateConsoleCtrlEvent work.

Googling this, it seems to be a widespread "feature" of Windows - rather than an AutoIt bug. See here for more (albeit non-AutoIt) discussion on this.

Edited by JonusC

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Sorry for double post, but it's worthy of a notification to all subscribed. I found a solution to this but with one caveat - it only works when the script is compiled.

GenerateConsoleCtrlEvent works, but the console needs to be "attached" first. Example below, all credits to rover 2k12.

EDIT: It also doesn't work if it's run by SciTE/Wrapper "#AutoIt3Wrapper_Run_After="%out%"" directive... so it's a very last-resort thing. But still better than doing a "kill process" IMO.

;coded by rover 2k12

;Ref:
;<a href='http://stackoverflow.com/questions/813086/can-i-send-a-ctrl-c-sigint-to-an-application-on-windows' class='bbc_url' title='External link' rel='nofollow external'>http://stackoverflow.com/questions/813086/can-i-send-a-ctrl-c-sigint-to-an-application-on-windows</a>

#NoTrayIcon
;#AutoIt3Wrapper_Change2CUI=y
If Not @Compiled Then Exit

#include <windowsconstants.au3>
Opt("MustDeclareVars", 1)

Global $iCallback
OnAutoItExitRegister("_Exit")
Global Const $CTRL_BREAK_EVENT = 1
Global Const $CTRL_C_EVENT = 0
Global $fCloseFlag = False

$iCallback = _InitConsole()
_Main()

Func _Main()
GUICreate("", 600, 400)
Local $iMemo = GUICtrlCreateEdit("", 2, 28, 596, 370, $WS_VSCROLL)
GUICtrlSetLimit(-1, 1048576)
Local $cCtrl_C = GUICtrlCreateButton("Ctrl-C", 2, 2, 120, 25)
GUISetState()

Local $iExitCode = Cmd("cmd.exe /c dir c:\ /s", $iMemo, $cCtrl_C)
MsgBox(262144, "Exit Code", $iExitCode & @TAB & @TAB & @TAB)

GUICtrlSetData($iMemo, "")
$iExitCode = Cmd("ping.exe -t " & @IPAddress1, $iMemo, $cCtrl_C)
MsgBox(262144, "Exit Code", $iExitCode & @TAB & @TAB & @TAB)

;Local $Archiv = @TempDir &amp; "\" &amp; @HOUR &amp; "_" &amp; @MIN &amp; "_" &amp; @SEC &amp; "_test.zip"
;GUICtrlSetData($iMemo, "")
;$iExitCode = Cmd(@ProgramFilesDir &amp; "\7-Zip\7z a -tzip "&amp;$Archiv&amp;" "&amp;@TempDir &amp; "\*.*", $iMemo, $cCtrl_C)
;MsgBox(262144, "Exit Code", $iExitCode&amp;@TAB&amp;@TAB&amp;@TAB)

;send ctrl-c to console process not launched by script
GUICtrlSetData($iMemo, "")
DllCall("kernel32.dll", "bool", "FreeConsole") ;free console so we can attach to another console process
MsgBox(262144, "Open CMD prompt", "open a single cmd prompt with ping.exe -t yourIP, then continue")
Local $aCon = WinList("[CLASS:ConsoleWindowClass]"), $PID
For $i = 0 To $aCon[0][0]
  $PID = WinGetProcess($aCon[$i][1])
  If $PID <> @AutoItPID Then DllCall("kernel32.dll", "bool", "AttachConsole", "dword", $PID)
Next
GUICtrlSetData($iMemo, "Ctrl-C to close existing console")

While 1
  Switch GUIGetMsg()
   Case -3
    ExitLoop
   Case $cCtrl_C
    ;send ctrl-c to script and child process event handler, script event handler will block exit
    DllCall("kernel32.dll", "bool", "GenerateConsoleCtrlEvent", "dword", $CTRL_C_EVENT, "dword", 0)
  EndSwitch
WEnd
DllCall("kernel32.dll", "bool", "FreeConsole")
Exit
EndFunc   ;==>_Main

Func _Exit()
DllCall("kernel32.dll", "bool", "FreeConsole")
DllCall("Kernel32.dll", "bool", "SetConsoleCtrlHandler", "ptr", 0, "bool", 0)
DllCallbackFree($iCallback)
EndFunc   ;==>_Exit

Func Cmd($sCmd, $cEdit, $cBtn)
Local $iPid = Run($sCmd, @ScriptDir, @SW_HIDE, 2)
Local $h_Process = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'int', 0x400, 'int', 0, 'int', $iPid)
Local $sData, $retval = -1
While 1
  $sData = StdoutRead($iPid)
  If @error Then ExitLoop
  $sData = StringReplace($sData, @CR & @CR, @CR)
  If $sData Then GUICtrlSetData($cEdit, $sData & @CRLF, 1)
  #cs
   If $fCloseFlag Then
   ;continually send ctrl-c until child process exits (not all child processes will respond to Ctrl-C the first time)
   DllCall("kernel32.dll", "bool", "GenerateConsoleCtrlEvent", "dword", $CTRL_C_EVENT, "dword", 0)
   If ProcessExists($iPid) = 0 Then ExitLoop
   EndIf
  #ce
  Switch GUIGetMsg()
   Case -3
    ;ExitLoop
   Case $cBtn
    ;send ctrl-c to script and child process event handler, script event handler will block exit
    DllCall("kernel32.dll", "bool", "GenerateConsoleCtrlEvent", "dword", $CTRL_C_EVENT, "dword", 0)
  EndSwitch
WEnd
$fCloseFlag = False
If IsArray($h_Process) Then
  Local $i_ExitCode = DllCall('kernel32.dll', 'ptr', 'GetExitCodeProcess', 'ptr', $h_Process[0], 'int*', 0)
  If IsArray($i_ExitCode) Then $retval = $i_ExitCode[2]
  DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $h_Process[0])
EndIf
Return $retval
EndFunc   ;==>Cmd

Func _InitConsole()
    DllCall("kernel32.dll", "int", "AllocConsole")
    ;DllCall("kernel32.dll", "bool", "AttachConsole", "dword", -1)
    Local $hConsolehWnd = DllCall("Kernel32.dll", "hwnd", "GetConsoleWindow")
    If @error Then Return
    WinSetState($hConsolehWnd[0], "", @SW_HIDE)
    Local $iCB = DllCallbackRegister("_ConsoleEventHandler", "long", "dword")
    DllCall("Kernel32.dll", "bool", "SetConsoleCtrlHandler", "ptr", DllCallbackGetPtr($iCB), "bool", 1)
    Return $iCB
EndFunc   ;==>_InitConsole

Func _ConsoleEventHandler($dwCtrlType)
Switch $dwCtrlType
  Case $CTRL_C_EVENT, $CTRL_BREAK_EVENT
   $fCloseFlag = True ; set flag for checking if child process exists
   Return True ; exiting blocked, exit must be called from loop
   ;Return False ;exit normally
EndSwitch
Return False
EndFunc   ;==>_ConsoleEventHandler
Edited by JonusC

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

  • Similar Content

    • fopetesl
      By fopetesl
      I need to be able to issue a command line which has a folder in parentheses as
       
      attrib +s +h "absolute folder to hide"  I've read through many posts here but nothing quite hacks how to use a variable as the folder in parentheses.
      I've tried
       
      Local $dosattrib = "attrib +s +h " & ""$hidFolder"" ; $hidFolder built up from decrypted encrypted C:\Hidden Folder which I do not want visible when compiled version is reverse engineered  which errors with excess parentheses but in single "" it doesn't work.
      There seems to be a relatively complicated method to make it work but surely there's a simple way?
       
       
    • TheDcoder
      By TheDcoder
      Hello Everyone , Are you tired of searching the forum for getting both the exit code & the stdout output? Then you are in the right place!

      With this UDF you can get the both output & exit code of the command or the console app! Or you can get the exit code of another process without having to use RunWait...
      Features:
      1. Simple & Lightweight (15 KB)
      2. Detailed comments & description
      3. Flexible functions with many optional parameters
      A BIG THANKS TO PsaltyDS for the functions! 2 of the (main) functions in the UDF are his work
       
      List of functions:
      Downloads:
      Grab the latest (in development) code from GitHub
       
      Hope it may help you, TD
       
      P.S Icon made by Freepik from www.flaticon.com, Modified by TheDcoder
    • Baboo85
      By Baboo85
      Hi all,
      I need to start a script that include:
      - admin privileges
      - multiple cmd commands
      - no bat, no exe, no tmp files created anywhere (especially in the user temp folder)
      In a bat file it would be simple, but users shouldn't see what commands I'm sending.
      Example of the script:
      echo off cls echo. echo I AM A TOOL echo. echo NOTE: echo - note 1 echo - note 2 echo - etc set USER1=0 set COMPUTER1=0 if /i %username% equ user.user ( set USER1=1 set COMPUTER1=1 ) if /i %username% equ another.user set USER1=1 if /i %computername% equ notebook set COMPUTER1=1 if %USER1% EQU 1 ( if %COMPUTER1% EQU 1 ( reg delete "HKLM\SOFTWARE\blablabla" /f ) else ( echo Computer not authorized. Contact assistance.) ) else ( echo User not authorized. Contact assistance.) echo. pause exit With the send("") is a disaster.
      I'm a noob here, so what can I do?
       
      EDIT: OR ELSE I explain the situation and what I need, so if there is a simple solution I can use that.
       
      SITUATION: our domain users have Users rights on the machine. Some of them need administrator rights.
      We create a local user with administrator rights, so that the users must insert username and password when asked to run something with administrator rights.
      We have an internal domain group policy that blocks EXE, BAT, COM, TMP files from the user local temp directory, for a security reason (malware). That also blocks most software installation.
      But some users are often out of office, away from workplace and in another country, they need a complete control on their computers.
       
      WHAT I NEED: I need to check the username and the computer name. If the username is the one with local administrator rights and the computer name is a computer that is qualified to temporary remove the policy, then I need to execute a REG DELETE command with administrator rights.
       
      I hope I explained myself.
       
      Thank you very much.
    • fopetesl
      By fopetesl
      I have problems running both Bat files and Command line instructions.
      This function hopefully shows what I have tried so far
      Global $fFileToCreate = "", $DOS ScanFilm($fFileToCreate) Func ScanFilm($fFileToCreate) MsgBox($MB_SYSTEMMODAL, "Scanning Status", $fFileToCreate) ; $DOS = Run(@ComSpec & " /c " & "scan.bat" & @CRLF, "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD) $DOS = Run(@ComSpec & " /k " & "ncat 192.168.1.6 80 <scant.txt >scanrep", "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD) ; $DOS = _RunDOS("ncat 192.168.1.6 80 <scant.txt >scanrep") ProcessWaitClose($DOS) $Message = StdoutRead($DOS) MsgBox($MB_SYSTEMMODAL, "Stdout Read:", $Message) Endfunc My first attempt running scan.bat reveals a bug in cmd.exe where the result of
      echo !SR | ncat 192.168.1.6 80 > scanrep is
      C:\S3_GUI\ncat>scan.bat C:\S3_GUI\ncat>echo scant.txt | ncat 192.168.1.6 80 1>scanrep Ncat: . C:\S3_GUI\ncat> note the added '1' which then throws the error, (when client is connected), "File or directory not found" so the command fails.  This has been run on four different computers running Windows 7 with same result.
      Next using Run() seems to truncate the command so $DOS reads:

      Using _RunDOS() doesn't throw any error but MsgBox() is empty.
       
       
       
       
       
       


    • dubi
      By dubi
      Hi,


       
      Background: i have a number of instances of the same application that I want to automate in parallel.

      Unfortunately, I cannot completely automate these instances in the background. So, from time to time these instances need to have the focus so that I can interact with the controls via “send” directly.

      Each of the application instances is controlled by a au3 complied script. Each script (called with a parameter) manages the automation of the respective application-instance. Each of the (complied) script (instances) is called by a (central) front end with a gui. The front end controls if the “focus” is available to do the “send” and “mouseclick” modifications. The central front end either allows a child to have the focus or prevents it to get the focus (in which case the child will wait and checks again). The code for the front end is included. Apologies for the lengthy explanation.


      #RequireAdmin #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <EditConstants.au3> #include <GUIEdit.au3> #include <ScrollBarConstants.au3> #include <Array.au3> Global Const $APF_ALLOWMULTILINE = 1 Global Const $APF_RIGHTALIGN = 6 Global Const $APF_RIGHTALIGNCOL = 2 Global Const $APF_RIGHTALIGNDATA = 4 Global Const $APF_PRINTROWNUM = 8 Global Const $APF_DEFAULT = $APF_PRINTROWNUM Global $PID[9], $FocusAvailable = True, $previousEditMsg Global $PID_waiting[0][2], $logfile $logfile = "D:\MultiInstance\Logfiles\FrontEnd.txt" If FileExists($logfile) Then FileDelete($logfile) #Region ### START Koda GUI section ### Form= $hGui_1 = GUICreate("Instanzenmanager", 493, 1226, 1807, 93) $grpInst1 = GUICtrlCreateGroup(" 1 ", 8, 8, 233, 121) $btnPause01 = GUICtrlCreateCheckbox("Pause", 16, 64, 50, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $tbnStop01 = GUICtrlCreateCheckbox("Stop", 16, 96, 218, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $btnMin01 = GUICtrlCreateCheckbox("Minimize", 72, 64, 66, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $btnWdh01 = GUICtrlCreateCheckbox("Restore", 144, 64, 90, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $btnStart01 = GUICtrlCreateCheckbox("Start", 16, 32, 218, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) GUICtrlSetBkColor(-1, 0x00FF00) GUICtrlCreateGroup("", -99, -99, 1, 1) $grpInst3 = GUICtrlCreateGroup(" 3 ", 8, 136, 233, 121) $btnPause03 = GUICtrlCreateCheckbox("Pause", 16, 192, 50, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $tbnStop03 = GUICtrlCreateCheckbox("Stop", 16, 224, 218, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $btnMin03 = GUICtrlCreateCheckbox("Minimize", 72, 192, 66, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $btnWdh03 = GUICtrlCreateCheckbox("Restore", 144, 192, 90, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $btnStart03 = GUICtrlCreateCheckbox("Start", 16, 160, 218, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) GUICtrlSetBkColor(-1, 0x00FF00) GUICtrlCreateGroup("", -99, -99, 1, 1) $grpInst2 = GUICtrlCreateGroup(" 2 ", 248, 8, 233, 121) $btnPause02 = GUICtrlCreateCheckbox("Pause", 256, 64, 50, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $tbnStop02 = GUICtrlCreateCheckbox("Stop", 256, 96, 218, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $btnMin02 = GUICtrlCreateCheckbox("Minimize", 312, 64, 66, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $btnWdh02 = GUICtrlCreateCheckbox("Restore", 384, 64, 90, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $btnStart02 = GUICtrlCreateCheckbox("Start", 256, 32, 218, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) GUICtrlSetBkColor(-1, 0x00FF00) GUICtrlCreateGroup("", -99, -99, 1, 1) $grpInst4 = GUICtrlCreateGroup(" 4 ", 248, 136, 233, 121) $btnPause04 = GUICtrlCreateCheckbox("Pause", 256, 192, 50, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $tbnStop04 = GUICtrlCreateCheckbox("Stop", 256, 224, 218, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $btnMin04 = GUICtrlCreateCheckbox("Minimize", 312, 192, 66, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $btnWdh04 = GUICtrlCreateCheckbox("Restore", 384, 192, 90, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $btnStart04 = GUICtrlCreateCheckbox("Start", 256, 160, 218, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) GUICtrlSetBkColor(-1, 0x00FF00) $Edit1 = GUICtrlCreateEdit("", 8, 720, 473, 497) $btnPauseAll = GUICtrlCreateCheckbox("Pause all", 8, 656, 474, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) $btnStopAll = GUICtrlCreateCheckbox("Stop all", 7, 688, 474, 25, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_PUSHLIKE)) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### While 1 CheckGuiMsg() FileWrite($logfile, @HOUR & ":" & @MIN & ":" & @SEC & "> " & "CheckGuiMsg" & @CRLF) CheckClientMessages() FileWrite($logfile, @HOUR & ":" & @MIN & ":" & @SEC & "> " & "CheckClientMessages" & @CRLF) WEnd Func CheckGuiMsg() $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $btnStart01 AddTextToEdit("Starting Instance 1") $PID[0] = Run("D:\XVM05\Entwicklung_FilterTest_Multi_ToFileV001.exe 1", @ScriptDir, Default, 3) Case $btnStart02 AddTextToEdit("Starting Instance 2") $PID[1] = Run("D:\XVM05\Entwicklung_FilterTest_Multi_ToFileV001.exe 2", @ScriptDir, Default, 3) Case $btnStart03 AddTextToEdit("Starting Instance 3") $PID[2] = Run("D:\XVM05\Entwicklung_FilterTest_Multi_ToFileV001.exe 3", @ScriptDir, Default, 3) Case $btnStart04 AddTextToEdit("Starting Instance 4") $PID[3] = Run("D:\XVM05\Entwicklung_FilterTest_Multi_ToFileV001.exe 4", @ScriptDir, Default, 3) Case $btnPause01 AddTextToEdit("Send Pause to Instance 1") StdinWrite($PID[0], "Pause") Case $btnPause02 StdinWrite($PID[1], "Pause") Case $btnPause03 StdinWrite($PID[2], "Pause") Case $btnPause04 StdinWrite($PID[3], "Pause") Case $tbnStop01 StdinWrite($PID[0], "Stop") Case $tbnStop02 StdinWrite($PID[1], "Stop") Case $tbnStop03 StdinWrite($PID[2], "Stop") Case $tbnStop04 StdinWrite($PID[3], "Stop") Case $btnPauseAll AddTextToEdit(@CRLF & "************Pause All not yet implemented**************" & @CRLF) Case $btnStopAll AddTextToEdit(@CRLF & "************Stop All not yet implemented***************" & @CRLF) EndSwitch EndFunc ;==>CheckGuiMsg Func CheckClientMessages() For $i = 0 To 3 FileWrite($logfile, @HOUR & ":" & @MIN & ":" & @SEC & "> " & $i & @CRLF) Local $a = TimerInit() $p = $PID[$i] $streamRead = StdoutRead($p) If $streamRead <> "" Then Switch $streamRead Case StringInStr($streamRead, "Focus Needed") > 0 If $FocusAvailable Then $FocusAvailable = False StdinWrite($p, "Focus Granted") Else EndIf Case StringInStr($streamRead, "Release Focus") > 0 StdinWrite($p, "Release Focus Received") $FocusAvailable = True Case Else EndSwitch EndIf FileWrite($logfile, @HOUR & ":" & @MIN & ":" & @SEC & "> " & $i & " " & round(TimerDiff($a),2) & @CRLF) Next EndFunc ;==>CheckClientMessages Func AddTextToEdit($text) If $previousEditMsg <> $text Then $previousEditMsg = $text GUICtrlSetData($Edit1, GUICtrlRead($Edit1) & @YEAR & "." & @MON & "." & @MDAY & " - " & @HOUR & ":" & @MIN & ":" & @SEC & "> " & $text & @CRLF) _GUICtrlEdit_Scroll($Edit1, $SB_SCROLLCARET) EndIf EndFunc ;==>AddTextToEdit



      My issue now is that the mechanism with with StdoutRead and StdinWrite is not efficient at all. The more instances I start the slower it gets. This is not just a bit slower (like a fraction of a second), but to the degree that the front end is not responding at all any longer (with 3 instances handling).

      So my questions are:

      1.       Is there a flaw in my implementation with StdoutRead and StdinWrite? (note that all works fine with 1 and also (slower) with 2 instances running) but actually breaks down with 3 instances running.

      2.       Can I optimize the currently used implementation so that I can control 30+ instances?

      3.       What other implementation do you see suitable for this approach?

      a.       I have already tried it with communication through files but observed that this is not sufficiently reliable with multiple instances.

      b.       Is Named Pipes a more performant approach (I am a bit scared of the effort to learn and implement this)

      c.       Any other method?


       
      Many thanks in advance

      -dubi