3
votes

I was writing a self-referencing Windows 10 (home ed.) batch script to locate a string in a large number of log files, create a results file and, when finished, open the log file in notepad++. This process sometimes takes a few minutes hence the self-referencing part which allows me to return control to the original command window until the log file is opened (and takes focus).

However, when the second command window, started with the "start" command and the "/b" switch, includes at least one "echo" command it won't exit cleanly and requires me to press the Enter key to fully exit that "nested" command window.

I've distilled the code down to nine lines so you can hopefully see what I mean. To see it in action, save the following as "test.bat" and run it from a command prompt:

@echo off
if "%1" EQU "" call :noArgs & goto :done
echo There was at least one argument.
:done
exit /b
:noArgs
echo There were no arguments.
start "" /b cmd /c test.bat arg1
goto :eof

It will print "There were no arguments." below the prompt followed by "There was at least one argument." at the prompt and then hang, waiting for the Enter key before returning control back to the prompt.

If you remove the line:

echo There was at least one argument.

the Enter key is no longer needed for the second command shell to exit. Similarly, if the output from the echo command is redirected to a file the issue goes away. This problem also occurs without echo commands but if output is generated from EG the type command so it seems it is due to there being some form of console output. This can be easily demonstrated by commenting out both the "echo" line as well as the first line "@echo off" - with commands now being echoed to the console it again hangs before exiting.

I could get around this issue by changing the "start" call to this:

start "" /min cmd /c test.bat arg1

however any output is no longer easily visible in the minimized window so it's a poor solution.

I'd love to know why the code I posted behaves the way it does, why it won't exit cleanly without requiring the Enter key to be pressed. The only clue I have is from the "remarks" column in the matrix on this page Close and exit batch files that states, "Make sure no text is displayed in the console window to make it close automatically at the end of the batch file". However that seems to refer only to Windows 9.x versions of command.com - not EG Windows 10 nor cmd.exe.

Thanks for any input/thoughts.

-s1m0n-

1
Same behaviour on my Windows 7 (x64) machine. Even when I just enter start /B (or start /B cmd which is equivalent) and then exit into the new cmd instance, I need an extra-enter to return to the main cmd instance... I don't think it has anything to do with cmd as in the link you provided; I guess this is caused by start /B... Unfortunately I cannot offer a solution for that...aschipfl
@RyanBemrose, what happens if you type start /B cmd /C echo Hi into your Windows 8.1 console? does it return immediately to the main cmd instance without having to press enter? what happens if you type start /B cmd /C break?aschipfl
I think Harry Johnston got it right as I can enter commands despite there being no visible prompt (cursor far left). What I can't figure out, and it could mean there is no simple solution, is how to force the prompt to display again so it looks normal and not hung up/waiting. -s1m0n-s1m0n
That depends on why you're running the child asynchronously in the first place. If you don't have any particular reason to do so, leave out the start command, i.e., just say cmd /c test.bat arg1. (It is possible to run a child asynchronously and wait for it before exiting, but it's a bit tricky.)Harry Johnston
I run the child asynchronously as it can take some minutes to finish and display its results. In the meantime I'd prefer to have command-line control back. I was able to get around the issue of having control back but sans a fresh command prompt in a rather curious way. I looked into how to display the prompt env var and it can be done for /F "tokens=1 delims=#" %%a in ('"prompt #%PROMPT%# & echo on & for %%b in (1) do rem"') do ( echo %%a ) from there it led me to including this line for the parent for /F %%a in ('call') do call which fixes it. I'll post the entire fix in another comment.s1m0n

1 Answers

4
votes

You're misinterpreting the output. If I've understood you rightly, it looks like this:

C:\working\test>test
There were no arguments.

C:\working\test>There was at least one argument.

That happened like this:

C:\working\test>                                    <---- output from first shell
                test                                <---- input
There were no arguments.                            <---- output from first shell
                                                    <---- output from first shell
C:\working\test>                                    <---- output from first shell
                There was at least one argument.    <---- output from second shell
                                                    <---- cursor is here

The second shell is running asynchronously - that's what start does - so the first shell has already finished the batch job and printed the next prompt by the time the second shell gets around to printing its output.

At this point, the second shell has exited, and the first shell is waiting for you to enter a command. It doesn't know that the second shell has printed anything, so it has no reason to think that it needs to reprint the prompt. But if you enter a command, it will work.