4

If we have a batch file being redirected to a log like so:

C:\Testing\Example.bat > C:\Testing\Example.log 

Is there any way inside the batch file to determine if there's a standard output redirect happening to a log file?

Basically the batch file I have requires three arguments passed to it. When arguments are left out, the batch file prints a usage example much like regular Windows commands would, and throws a 'pause' out so instructions can be read. However if the batch is called without arguments AND it's being logged, then the batch file will just sit there forever waiting for a key to break the pause, but won't show anything on the screen.

Normally this wouldn't be a problem at all, however I'm trying to make this idiot-proof since I won't be the one implementing the batch file in other scripts/scheduled tasks.

At this point it seems like I need to get rid of the usage pause entirely, but I was hoping for a solution where I wouldn't have to. Thanks for the help.

3
  • Instead of using pause, you could use the choice command with a timeout. Commented Mar 20, 2013 at 21:16
  • 1
    It's possible to detect redirection and also if a pipe is active, How to detect if input comes from pipe or redirected file. But you could also read this Dostips:foolproof counting of arguments, how streams really works. Commented Mar 20, 2013 at 21:58
  • Jeb thanks for linking this documentation, it was certainly interesting to see what's actually happening with streams. Due to the complexity of setting up those examples though, I felt it would just complicate the batch file past the level I was comfortable with. I ended up just exiting the batch file if key parameters were missing, and linked the instruction label to [%1]==[/?] or [%1]==help center Commented Mar 22, 2013 at 12:53

5 Answers 5

4

There is no good way to determine if stdin or stdout has been redirected using native batch commands.

But there is no need to worry about redirection in your case. Simply redirect the PAUSE stdin and stdout to con, and you don't have to worry about prior redirection.

pause <con >con 

Update

It is possible to cleanly detect whether stdin and/or stdout and/or stderr has likely been redirected. But I haven't figured out a way to non-destructively determine which of those handles was redirected.

@echo off 2>nul (5>&4 break) && ( >con echo There has been redirection ) || ( >con echo No redirection found ) 

The technique relies on the fact that whenever an existing handle is redirected, the old definition is saved in the lowest available undefined handle.

If there has not been any redirection, then 2>nul saves stderr in 3, and 4 is undefined. So 5>&4 fails, and the || branch is fired.

If there has been redirection, then 3 has already been defined to preserve the original value of the redirected handle, so 2>nul will save stderr in 4 (unless 4 has also already been used by some other redirection). Either way, the 5>&4 will succeed because 4 is defined, so the && branch will fire.

If the test reports that there has been redirection, then at least one of the following must be true:

  • stdin redirection
  • stdout redirection
  • stderr redirection
  • handle 4 defined directly with something like 4>"log.txt"
  • handle 5 defined directly with something like 5>"log.txt"

Unfortunately, I cannot determine which of the above are true, except for...

Over at DosTips, SiberiaMan has published a simple technique to determine if stdin has been redirected or is receiving a pipe:

2>nul >nul timeout /t 0 && ( >con echo stdin not redirected or piped ) || ( >con echo stdin has been redirected or is receiving piped input ) 
Sign up to request clarification or add additional context in comments.

3 Comments

This doesn't solve the problem of the pause happening when the batch file was redirected. The original goal was to try and have the pause only happen when it was opened directly.
I guess I misunderstood your goal. The con solution will display the pause message on the screen and wait for keyboard input properly, regardless of redirection. But if you want it to be fully automated without pause if there is redirection, then no, this does not solve the problem.
Still cool, I'm logging away this approach if I ever need it in the future. I appreciate you giving a 5-year old question a shot.
2

I am not aware of any way to do this using only batch and standard commands. However, there are tricks that can be used from other languages such as native C or C# programs, if it's important enough to you to include another .exe along with your .bat.

1 Comment

Thanks for the quick reply Nate. Comically enough I would have preferred doing this entirely in C#, and in fact most of the real work in the batch file is from an exe file I put together. However the project admins cried foul because they wanted something easily modifyable without needing to recompile. I'm on board with that concept, so my next stop was in fact powershell, which also got shot down because "we don't know what that is or how to use it". I can't seem to win one today... maybe if I really push for it they'll let me go Powershell, but for now I'm stuck with good old DOS.
1

I think you just ask the wrong question. you want to find a way to end the batch with extra break when in cmd mode. and stop in batch mode without pausing. You can use CMDpause this will make a variable named cmdpause examples https://www.administrator.de/wissen/batchcode-erstellen-fehler-batch-leichter-finden-184736.html https://www.dostips.com/forum/viewtopic.php?t=7257#p47510

there is something from Dave and jeb. But I have no link.

Phil

Comments

1

You could check if stdout is redirected with a small trick.
It uses the fact that outputting backspaces after a TAB moves the cursor back and if the cursor shall be moved before the home position in this situation, an error will be created to get a hint in your logfiles for the strange characters.

The drawback is, that it outputs <FF><TAB>><BACKSPACE><BACKSPACE><CR><LF> to stdout.
When stdout is the console, it simply clears it.
But when stdout is redirected to a file you append these characters to the file, but it can be commented with a meaningful text.

@echo off setlocal call :createTAB_BS echo Script started, test for redirection: cls ( echo %%TAB%%%%BS%%%%BS%%) | ( findstr "^" 2^> nul) if %errorlevel% EQU 0 ( >CON echo stdout is redirected ) ELSE ( echo stdout goes to the console ) exit /b :createTAB_BS for /f "tokens=1,2 delims=," %%A in ('forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x09,0x08"') do ( set "TAB=%%A" set "BS=%%B" ) exit /b 

Comments

0

There isn't a way in standard Windows batch files (that I'm aware of) to determine where STDOUT is being redirected, or even if it is being redirected. However, you might wish to write your usage examples out to STDERR instead of STDOUT, so at least a simple redirect into a file will not capture the usage info.

Example test.cmd:

@ECHO OFF ECHO Test output 1>&2 PAUSE 1>&2 

Then call it:

test.cmd > output.log 

Which will still output:

Test output Press any key to continue . . . 

Of course, this does nothing for when the file is called with STDERR being redirected.

test.cmd 2> error.log 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.