XP anomaly/bug

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

XP anomaly/bug

#1 Post by Ed Dyreen » 24 May 2014 21:39

I have reported this longtime age, and found a similar case.

Code: Select all

@echo off &prompt $g &setlocal enableDelayedExpansion &set $lf=^


::
%=   =%set ^"$n1c=^^^%$lf%%$lf%^%$lf%%$lf%^<nul ^^"
%=   =%set ^"$c1=%%~#^<nul ^^"
%=   =%set "echon_=echo("
%=   =%set "echo_=<nul set/p="
%=   =%set "necho_=%echon_%&%echo_%"
%=   =%set "n2echo_=%echon_%&%necho_%"
%=   =%set "forQ_=for %%? in"
%=   =%set "e5=^^^^^"
%=   =%set "e7=%e5%^^"
%=   =%set "e15=%e7%%e7%^"
%=   =%set "e31=%e15%%e15%^"
:: (
%=   =%for %%# in ("") do set ^"cmdMacro=%forQ_% (1,2) do if %%?==2 (setlocal enableDelayedExpansion%%$lf%%%$c1%
%$c1%
%=      =%!necho_!  This works %e31%!%%$lf%%%$c1%
%$c1%
%=   =%endlocal)else set $="
   ::
   ( %n2echo_%cmdMacro=!cmdMacro!_ )

   setlocal enableDelayedExpansion
   :: (
      ( %n2echo_%  enaDelayed, /v:on, pipe )
      ( cmd /v:on /e:on /t:0B /q /c "%%cmdMacro%%" ) 2>nul >con |(rem^ )
   :: )
   endlocal
:: )
endlocal

pause
exit
Running the above code gives this output on XP

Code: Select all

cmdMacro=for %? in (1,2) do if %?==2 (setlocal enableDelayedExpansion%$lf%echo(&<nul set/p=  This works ^^^^^^^!%$lf%endlocal)else set $=_

  enaDelayed, /v:on, pipe ♪◙  This works ^!Druk op een toets om door te gaan. . .
Pay close attention to the ♪◙ symbol, where did this character come from ?

Code: Select all

Microsoft Windows XP [versie 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Documents and Settings\Administrator>^N
♫ wordt niet herkend als een interne
of externe opdracht, programma of batchbestand.

C:\Documents and Settings\Administrator>
It seems to be a LALT+14 :?:

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: XP anomaly/bug

#2 Post by penpen » 25 May 2014 02:26

The characters displayed are \r\n:

Code: Select all

Z:\>>con cmd /C echo \r\n == 
\r\n == ♪◙
Z:>
The inner command instance handles them as special keys. But as the output is redirected to console directly,
the outer cmd instance cannot treat them as special characters, as this instance is bypassed.
So the result is, that the glyphs of \r\n are rendered.

If you don't want to see these glyphs, then in this case this may help:

Code: Select all

Z:\>cmd /C echo \r\n == ^>con
\r\n ==

Z:>

Although this misuses the STDERR stream, this may help you (as you send all errors to nul):

Code: Select all

      ( (cmd /v:on /e:on /t:0B /q /c "%%cmdMacro%%") 2>nul) >&2 |(rem^ )
   :: ) 2>con


penpen

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: XP anomaly/bug

#3 Post by Ed Dyreen » 26 May 2014 18:00

Sorry I don't understand.

Code: Select all

      ( ( cmd /v:on /e:on /t:0B /q /c "%%cmdMacro%%" ) 2>nul ) >con |(rem^ )

Code: Select all

  enaDelayed, /v:on, pipe ♪◙  This works ^!Druk op een toets om door te gaan. .
The inner cmd sends stderr to nul, but above output tells me ♫ is not part of stderr as it is not send to nul 2>nul

Code: Select all

      ( ( cmd /v:on /e:on /t:0B /q /c "%%cmdMacro%%" ) 2>nul ) >&2 |(rem^ )

Code: Select all

  This works ^!Druk op een toets om door te gaan. . .
So the ♫ which was not send to nul 2>nul, gets redirected to stderr >&2, but the nul redirection was already closed inside the previous code block. So how come your code works ?

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: XP anomaly/bug

#4 Post by penpen » 27 May 2014 07:05

The redirection should be computed from outer (blocks) to inner (ones).
I've no idea how to explain that without abstraction; let the notation be this:

Code: Select all

A  :=  B 2>con == ( ( ( cmd /v:on /e:on /t:0B /q /c "%%cmdMacro%%" ) 2>nul ) >&2 |(rem^ ) ) 2>con
B  :=  ( C | F )
C  :=  ( D >&2 )
D  :=  ( E 2>nul)
E  :=  ( cmd /v:on /e:on /t:0B /q /c "%%cmdMacro%%" )
F  :=  (rem^ )
-> :=  is redirected to
Then these redirections are performed:
initial: STDIN -> STDIN_A, STDOUT_A -> STDOUT, STDERR_A -> STDERR
2 > con: STDERR_B -> con
piping: STDIN_B -> STDIN_C, STDOUT_C -> STDIN_F, STDERR_C -> STDERR_B, STDOUT_F -> STDOUT_B, STDERR_F -> STDERR_B
> & 2 : STDOUT_D -> STDERR_C
2 > nul: STDERR_E -> nul

So this is the result for both inner commands (E, F):
STDIN_E == STDIN_D == STDIN_C <- STDIN_B == STDIN_A
STDOUT_E == STDOUT_D -> STDERR_C -> STDERR_B -> con.
STDERR_E -> nul

STDIN_F <- STDOUT_C
STDOUT_F -> STDOUT_B == STDOUT_A
STDERR_F -> STDERR_B -> con

penpen

Post Reply