3

I want my batch script to run a batch script, which doesn't terminate, then run several more batch scripts, which do terminate, and then close the first batch script.

The issue is, the first batch script I start needs to establish a connection before I can start running the others, and to determine when that's done I need to watch the output of the first script I start for the string that indicates that the connection is established.

In pseudo-code,

start first script
wait for first script to output specific string
while the first script remains running:
    run several other scripts
close the first script

This string will appear only after several previous lines have been printed. Both the number of lines and the time this takes can vary. The strings are not outputted all at once. I cannot modify this script.

The desired result is this:

C:\>first_batch_script.bat
Some line
Doing a thing
Winning the points
The Sims did this joke better
Connection established
certain string
C:\>other_batch_script.bat
other_batch_script is done!
C:\>another_batch_script.bat
another_batch_script is done!
C:\>REM kill first_batch_script.bat

This is the code I'm trying:

FOR /f "tokens=* delims=" %%L IN ('first_batch_script.bat ^| find "certain string"') DO echo %%L
call other_batch_script.bat
call another_base_script.bat
REM kill first_batch_script.bat

Using FOR /f seems promising, but when I run this the batch script runs quite slowly and then seems to hang. In any event, even if it ran through, I'm not seeing a good way to then break out of the loop and continue executing my code

Using START /WAIT doesn't help because the first script I start doesn't (and shouldn't) terminate. Using any kind of timing method just won't work because it can take fairly different amounts of time for the connection to be established.

So, long and short:

How do I monitor the output of a batch script, and only execute additional scripts once a certain string has been seen?

4
  • Can you share with us the script you have so far? And what exactly is your question?
    – CharlieRB
    Jun 13, 2014 at 19:55
  • Is there a certain reason it has to be a batch script? If not you could look if you can achieve you goal using scrpting language / programm called AutoIt. You even could combine batch and AutoIt if needed. Jun 13, 2014 at 20:07
  • @IvanViktorovic Feel free to give an answer using that, but I would much prefer this just be a quick, simple piece of code I need, not extra dependencies I need to introduce to this. But if it's the best way, it's the best way.
    – KRyan
    Jun 13, 2014 at 20:12
  • @CharlieRB Sorry about that, fixed.
    – KRyan
    Jun 13, 2014 at 20:52

2 Answers 2

2

If I understood your requirement correctly, then for /f will not work as it waits till inner process ends. You could try to synchronize on the file, like in this example:
(this would be your depended scripts file, say wait.bat) :

@echo off

:loop
timeout /t 1
(type res.txt |find "trip")  > nul 2>&1
if errorlevel 1 goto loop
echo I can go!

start it in cmd window, then open second cmd (same dir) and run (again, as an example):
ping localhost |find "trip" >res.txt
You should see 'I can go' only after ping outputs 'trip' (yes it quits shortly after, but your main script/process does not need to)

Please also note that normally you would start your main script first! This also ensures that the synchro file gets emptied.

You have not said what exactly you need to wait for - maybe there is a more straightforward way of checking that? (eg. using netstat to check open connections)?

5
  • I didn't say what exactly I'm waiting for precisely because I am not interested in answers that try to explore those alternatives. At any rate, thank you for confirming my fears re: FOR /f; I was hoping someone would know of a workaround for that. Anyway, this answer does not help me because I cannot modify the script I'm running (such edits would just get wiped out when the script is updated, and I'm not authorized to push such a change), but I appreciate the information, so +1.
    – KRyan
    Jun 13, 2014 at 22:03
  • you do not need to modify it. Put your master (ping in my example) command in one batch file, put your dependent scripts into second batch below the loop (where I put 'I can go') and create third batch which will just start the other two (with start)
    – wmz
    Jun 13, 2014 at 22:15
  • sorry even easier: Put your master (ping in my example) command in one batch file, put start myMaster.bat at top of wait.bat, put your dependent scripts below loop (where I put 'I can go')
    – wmz
    Jun 13, 2014 at 22:23
  • Ah, I think I see. I cannot test it right at this moment, but I believe this will work. I'll accept once I have confirmed that.
    – KRyan
    Jun 13, 2014 at 22:33
  • Thank you, it works perfectly. Took me a it to figure out what you meant put where, but it works.
    – KRyan
    Jun 16, 2014 at 16:57
-1

It sounds like you are using the wrong approach. There are operators which you can use to pipe the output to something, but also to pipe something into a program.

The second method will allow you to control a commandline program such as FTP.exe, and by what you're writing, it sounds like this is exactly what you need.

Create a textfile that has all the keypresses you need to do yourself, press an enter when an enter is necessary, so each command appears on its own line.

For example input.txt:

MyUsername
qwertyPasswd
y
2
3
quit

The above will first enter MyUsername and press enter. Then it will write the second line, etc.

Now, start your program and pipe the textfile into it:

C:\>ftp.exe <input.txt

.

A breakdown of the commands:

C:\>ftp.exe this is an example of a program you could be running.

<input.txt note the < character, this inputs the content of input.txt and treat it as userinput.

Note that if the program does not expect keyboard input, the pipe will wait supplying it.

4
  • No, this isn't even remotely what I need. The commands that I issue aren't commands in the first program, but rather separate batch scripts. They just use the connection established by the first program.
    – KRyan
    Jun 13, 2014 at 20:11
  • You can also use the output of one script as the input for another. Maybe it still works. In order to do this use the | character. Program1|Program2 where program1's output will be transmitted to the output of program2. (or script in this case)
    – LPChip
    Jun 13, 2014 at 21:10
  • I'm not familiar enough with Windows scripting, but how well is that going to work when the first script is outputing multiple lines at separate instances. If the piped script runs as soon as it gets any input, it won't get the string. If it waits for the first script to terminate, that's just not going to happen because it doesn't (and shouldn't) terminate.
    – KRyan
    Jun 13, 2014 at 21:14
  • I can't answer that because I have insuffucient knowledge of your script. You should try it out and see what happens.
    – LPChip
    Jun 13, 2014 at 22:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .