6

This is a minimal example that illustrates my problem:

:: test.bat
@echo off
call test2.bat 2>&1 | findstr foo
echo done calling test2

:: test2.bat
@echo off
start /B notepad >NUL
echo done starting child process

In this sample, findstr will not complete until notepad is closed, presumably because notepad has inherited stdout from the parent cmd process. How can I modify test2.bat so that test.bat doesn't hang?

Aaron
  • 594
  • 2
  • 12
  • 1
    notepad doesn't use or have a stdout. It's a GUI program. `/b` is meaningless here. So is `>nul` (there is no console output) –  Mar 18 '16 at 19:02
  • The problem I'm solving has nothing to do with notepad. I'm only using it as an example. I just need to be able to start a program that doesn't terminate, and not have test.bat hang. – Aaron Mar 18 '16 at 21:43
  • It's not a minimal example. There is no tee command in windows -no one can run it. –  Mar 18 '16 at 22:07
  • 1
    @Noodles, dude... Who are these comments helping? If you know of another built-in batch command that would also reproduce this problem, feel free to suggest it. – Aaron Mar 18 '16 at 22:17
  • We can't run the code. I told you how to fix the start command, I've told you your hypothesis about file handles doesn't apply to notepad. If I replace tee with findstr it works. Even without fixing all the other errors. Here's one more error. `REM` is the comment command in batch. –  Mar 18 '16 at 22:30
  • It also works with my tee utility http://stackoverflow.com/questions/28263236/batch-file-ping-output-to-text-file –  Mar 18 '16 at 22:40
  • It's not a programming issue but a configuration issue. See www.superuser.com –  Mar 18 '16 at 22:42
  • @Noodles, fine, replaced "tee" with "findstr". The behavior is the same- I still don't see "done calling test2" until I close notepad. Why do think handle inheritance doesn't apply to notepad? – Aaron Mar 18 '16 at 22:42
  • 2
    @Noodles, notepad doesn't *use* the standard output, but it still inherits a copy of the handle. Aaron's analysis is spot on. – Harry Johnston Mar 18 '16 at 22:43
  • I don't think there is any built-in solution. One of the batch-command gurus might know something clever you can do. Personally, I'd write a very simple executable to call CreateProcess with inheritance disabled. – Harry Johnston Mar 18 '16 at 22:46
  • Thanks, @HarryJohnston, that's what it was starting to look like to me, too. I'll probably do just what you suggest. – Aaron Mar 18 '16 at 22:50
  • I'm puzzled why @Noodles doesn't seem to be able to reproduce the problem, though. I can repro it with both findstr and the linked `tee` script. That might mean they are doing something slightly different which resolves the issue somehow, or has a non-standard configuration which makes it work, or perhaps is just using a different version of Windows. (I'm on Windows 7, FWIW.) – Harry Johnston Mar 18 '16 at 22:58
  • @HarryJohnston - I don't have any clever workaround, - your executeable/CreateProcess suggestion may be the best bet. But in [my answer](http://stackoverflow.com/a/36098045/1012053) I do prove that there is something very odd happening with inherited I/O handles/streams. (I'm not sure which term applies) – dbenham Mar 19 '16 at 12:34
  • The best workaround I found is to use powershell in place of the start command. See here: https://stackoverflow.com/a/53321347/5932003 – kostasvs Nov 15 '18 at 14:37

1 Answers1

4

I believe I can illustrate the problem without any batch file at all. The following pipe construct does not complete until after notepad.exe is closed:

start notepad | findstr "^"

I would expect that notepad would be executing in a new process that is totally disassociated from the cmd.exe pipe, and the only thing being piped would be the output of the START command itself (which is none). The START command returns "instantly", yet the pipe remains open for as long as notepad is running.

I don't know if it is an inherited I/O stream that is keeping the pipe open, but I can prove that the notepad process is inheriting streams in a way that might be the root of the problem. This is basically the same issue that was brought up at Issue with output redirection in batch.

Here is a simple batch script: test.bat

@echo off
call :test >nul
echo done calling test.bat
exit /b

:test
start notepad

Notice that stdout has been redirected to NUL when notepad is STARTed, due to the redirection of call :test >nul.

Now look at what happens when I issue a series of commands from the command line, starting off with test.bat having stdout redirected to a file:

C:\test>test.bat >test.txt

C:\test>REM The command returns immediately, and notepad remains open

C:\test>type test.txt
done calling test.bat

C:\test>echo This fails as long as notepad remains open >test.txt
The process cannot access the file because it is being used by another process.

C:\test>type test.txt
done calling test.bat

C:\test>REM Now I close notepad

C:\test>echo This works once notepad is closed >test.txt

C:\test>type test.txt
This works once notepad is closed

C:\test>

I am still blown away by this behavior. It seems totally illogical.

I don't think there is any way to prevent the stream inheritance with cmd.exe.

Perhaps Harry Johnston's suggestion could solve the issue (from the question comments): "I'd write a very simple executable to call CreateProcess with inheritance disabled."

Community
  • 1
  • 1
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • You could add `type test.txt` immediately prior to the first `REM` (or anywhere before closing `notepad`) to make your sample more demonstrative. Moreover, I tried to modify `test.txt` with supposed `Error saving file "test.txt"` message however my preferred text editor did not show routine _opened read-only_ indicator in this case. – JosefZ Mar 19 '16 at 15:30
  • @JosefZ - The content of test.txt is irrelevent. Morever, it is empty because my redirection is using overwrite mode. I don't understand your "favorite text editor" result. i am unable to save a file as test.txt using my favorite editor (ConTEXT) while Notepad remains open. Additionally, my Notepad session cannot save a file as test.txt either, it blocks itself! – dbenham Mar 19 '16 at 16:35
  • 1
    The `test.txt` is not empty but contains `done calling test.bat`, i.e. exactly output from `test.bat >test.txt` – JosefZ Mar 19 '16 at 16:59
  • @JosefZ - Doh! Of course you are correct. I'll add some TYPE commands to show the content at various points, though I am not sure it makes the issue any clearer. – dbenham Mar 19 '16 at 17:15
  • From a Win32 perspective, there's nothing surprising about this behaviour. The cmd.exe process has a handle to test.txt open when it starts notepad, and notepad inherits this handle. Whether the handle is declared as a standard I/O stream to the child process isn't relevant, so long as a duplicate of the original handle is still open the file will be locked, or, in the case of a pipe, the pipe won't close. (As of Vista this *could* have been fixed by changing cmd.exe so that it only allowed the standard handles to be inherited, but that would undoubtedly break existing code.) – Harry Johnston Mar 19 '16 at 21:58
  • @HarryJohnston - I suppose nothing is surprising once you know how it works. But why should notepad inherit the handles? Substitute cmd.exe for notepad, and it too inherits the handles, yet cannot (or doesn't know how to) interact with them in any way. IMO the logical design would have been to either pass the handles in a way they can be used, or don't pass them at all. But MS did neither, and I find that illogical/surprising. In my mind it is a design flaw, borderline bug. – dbenham Mar 20 '16 at 13:05
  • 1
    When cmd.exe was written, the designers didn't have any choice. Up until Vista, the kernel didn't let you pick and choose which handles were to be inherited. It was all or nothing, and nothing wasn't an option because that would break standard handle redirection. (One could arguably still hold Microsoft *as a whole* responsible, but those were simpler times and it probably didn't seem all that important.) – Harry Johnston Mar 20 '16 at 20:28
  • @HarryJohnston - Thanks for the info. – dbenham Mar 20 '16 at 21:06