KEYS as boolean variable within brackets and without delayed expansion

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

KEYS as boolean variable within brackets and without delayed expansion

#1 Post by npocmaka_ » 21 Jan 2016 07:51

Nothing useful , just observation over KEYS internal state and how it differs from ECHO.
KEYS changes its state even if it's called within brackets or in conditional execution statements and to child threads/processes spawned with pipes or FOR (unlike ECHO):

Code: Select all

@echo off

setlocal disableDelayedExpansion

set "if_on=for /f "tokens=3" %%# in ('keys') do if %%#==on. "
set "if_off=for /f "tokens=3" %%# in ('keys') do if %%#==off. "

rem :: echo state cannot be examined so easy
::for /f "tokens=3" %%# in ('echo') do echo %%#
::echo|for /f "tokens=3" %%# in ('more') do echo %%#
::echo|find "on."
(

   keys on
   %if_on% echo Should be displayed
   %if_off% echo Should be not
   keys off
   %if_off% echo Should be displayed
   %if_on% echo Should be not
   (
     keys on
   )
   %if_on% echo Should be displayed
   %if_off% echo Should be not

)


For sure this is slower than IF DEFINED (which also works in brackets context)
KEYS state can be examined also with pipes and FIND/FINDSTR - but probably will be slower.

The only case where this eventually (but probably will be never needed) can be easier for use is if IF DEFINED is piped. Rather is just

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: KEYS as boolean variable within brackets and without delayed expansion

#2 Post by dbenham » 21 Jan 2016 13:53

The ECHO state also changes within a code block, but commands that have already been parsed are not echoed if the state was OFF before the block was parsed. The only exceptions are the DO commands within a FOR loop.

Code: Select all

@echo off
(
  echo on
  echo
  for %%. in (.) do REM This command should echo
  echo off
  echo
  for %%. in (.) do REM This command should not echo
)

--OUTPUT--

Code: Select all

ECHO is on.

D:\test>REM This command should echo
ECHO is off.


Dave Benham

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: KEYS as boolean variable within brackets and without delayed expansion

#3 Post by npocmaka_ » 22 Jan 2016 03:42

The thing is you cannot detect echo state without temp file (at least I couldn't find a way ):
( And I think it's impossible to detect @() block )

Code: Select all

@echo off

(
   (echo)|more
   for /f "tokens=*" %%a in ('echo') do echo %%a
   
)


For and pipes resets its state.

And here I saw your echo_on macro (great trick by the way :) ).

Because pipe resets the state of the echo also this can be used:

break|for %%a in (.) do echo something


without a need to add echo off after using it (but probably will hit the performance a little bit).

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: KEYS as boolean variable within brackets and without delayed expansion

#4 Post by npocmaka_ » 27 Jan 2016 05:00

And VERIFY state also cannot be examined without a temp file:

Code: Select all

  for /f "tokens=3" %%a in ('verify') do @echo -%%a- 
  verify on
  for /f "tokens=3" %%a in ('verify') do @echo -%%a-


this will always print off.

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: KEYS as boolean variable within brackets and without delayed expansion

#5 Post by foxidrive » 27 Jan 2016 06:44

Gee, it's even worse than that!

Code: Select all

@echo off
verify on
verify|find "is"
verify
  pause



VERIFY is off.
VERIFY is on.
Press any key to continue . . .

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: KEYS as boolean variable within brackets and without delayed expansion

#6 Post by npocmaka_ » 27 Jan 2016 06:46

foxidrive wrote:Gee, it's even worse than that!

Code: Select all

@echo off
verify on
verify|find "is"
verify
  pause



VERIFY is off.
VERIFY is on.
Press any key to continue . . .


Yes.The case is the same as ECHO.
The pipes creates new threads/cmd contexts (on both sides) which are with some default states reset.Including ECHO and VERIFY

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: KEYS as boolean variable within brackets and without delayed expansion

#7 Post by dbenham » 27 Jan 2016 07:05

By default, there is no KEYS environment variable defined.

But issuing KEYS ON will set variable KEYS=ON, and KEYS OFF will set KEYS=OFF. This is true, even if you preset a KEYS variable to some bogus value.

Unfortunately, ECHO and VERIFY do not follow this same behavior. :(


Dave Benham

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: KEYS as boolean variable within brackets and without delayed expansion

#8 Post by jeb » 27 Jan 2016 08:21

There could be an echo state check without temporary files, but currently I only get the half.

Code: Select all

@(
  for %%A in (1) do break
) 1>&0


In the case of echo off it works without any error message or side effect.
With echo on it outputs (in german)

Das System kann nicht auf das angegebene Gerät schreiben.
Das System kann nicht auf das angegebene Gerät schreiben.
Das System kann nicht auf das angegebene Gerät schreiben.
Das System kann nicht auf das angegebene Gerät schreiben.


but: Nor it changes the errorlevel neither I can get the || logic working.

Code: Select all

@(
  for %%A in (1) do break || ECHO No Effect
) 1>&0 || ECHO No Effect


Perhaps someone get a better idea.

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: KEYS as boolean variable within brackets and without delayed expansion

#9 Post by dbenham » 27 Jan 2016 12:02

jeb wrote:There could be an echo state check without temporary files, but currently I only get the half.

Code: Select all

@(
  for %%A in (1) do break
) 1>&0


In the case of echo off it works without any error message or side effect.
With echo on it outputs (in german)

Das System kann nicht auf das angegebene Gerät schreiben.
Das System kann nicht auf das angegebene Gerät schreiben.
Das System kann nicht auf das angegebene Gerät schreiben.
Das System kann nicht auf das angegebene Gerät schreiben.


Great idea, and so close...

jeb wrote:but: Nor it changes the errorlevel neither I can get the || logic working.

Code: Select all

@(
  for %%A in (1) do break || ECHO No Effect
) 1>&0 || ECHO No Effect


Yep, I ran into basically the same issue at I/O error detection is broken The only way I was able to detect an I/O error was via a temporary file... Aaargh :twisted:

It really seams like a dead end.


Dave Benham

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: KEYS as boolean variable within brackets and without delayed expansion

#10 Post by npocmaka_ » 27 Jan 2016 15:52

I still have troubles to get this redirection tricks...

Whats the point to send 1 to 0 ?

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: KEYS as boolean variable within brackets and without delayed expansion

#11 Post by dbenham » 27 Jan 2016 15:57

The redirection of stdout to stdin "succeeds", but any attempt to actually write to stdin will of course fail.

When ECHO is off, there is no output, so no error message.

When ECHO is on, then the echo of the command fails and we get error messages. But it doesn't do us any good because we have no way to programmatically detect the error message unless we redirect stderr to a temp file.

It is possible to do staged redirection and effectively capture stderr with FOR /F, but the FOR /F launches a new cmd session with the ECHO defaulting to ON, regardless of the parent state. It's all very frustrating.


Dave Benham

npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: KEYS as boolean variable within brackets and without delayed expansion

#12 Post by npocmaka_ » 28 Jan 2016 02:35

dbenham wrote:The redirection of stdout to stdin "succeeds", but any attempt to actually write to stdin will of course fail.

When ECHO is off, there is no output, so no error message.

When ECHO is on, then the echo of the command fails and we get error messages. But it doesn't do us any good because we have no way to programmatically detect the error message unless we redirect stderr to a temp file.

It is possible to do staged redirection and effectively capture stderr with FOR /F, but the FOR /F launches a new cmd session with the ECHO defaulting to ON, regardless of the parent state. It's all very frustrating.


Dave Benham


Aha :!: thanks.

Post Reply