ComSpec strange behaviour

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

ComSpec strange behaviour

#1 Post by jeb » 09 Mar 2016 02:41

Hi,

base on the post SO: Executing command with FOR /F — “command not found”.
I tested the behaviour of ComSpec.

If you open a new cmd.exe window and try

Code: Select all

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. Alle Rechte vorbehalten.

C:\>set ComSpec=XXX

C:\>FOR /F %A in ('set APP') do @echo %A
Der Befehl "set test" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.

C:\>set ComSpec=C:\windows\system32\cmd.exe

C:\>FOR /F %A in ('set APP') do @echo %A
Der Befehl "set test" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.


Okay the first FOR /F fails as ComSpec is invalid, but why the second FOR fails too?

Next test in a fresh cmd.exe window

Code: Select all

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. Alle Rechte vorbehalten.

C:\>FOR /F %A in ('set App') do @echo %A
APPDATA=C:\Users\Jan

C:\>set ComSpec=XX

C:\>FOR /F %A in ('set App') do @echo %A
APPDATA=C:\Users\Jan


Wow :o, even the second FOR works!

It seems that ComSpec will be cached internally when it's used the first time.

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

Re: ComSpec strange behaviour

#2 Post by jeb » 09 Mar 2016 03:05

Some more tests show that the cached value will only be used for FOR/F,
but for pipes the ComSpec variable is used.

Code: Select all

C:\>set ComSpec=XX

C:\>FOR /F %A in ('set APP') do @echo %A
Der Befehl "set APP" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.

C:\>echo Pipe | more
Der Befehl ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.

C:\>set ComSpec=C:\Windows\System32\cmd.exe

C:\>FOR /F %A in ('set APP') do @echo %A
Der Befehl "set APP" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.

C:\>echo Pipe | more
Pipe


And the Start command seems to ignore ComSpec at all

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: ComSpec strange behaviour

#3 Post by einstein1969 » 09 Mar 2016 03:08

Nice find! :)

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

Re: ComSpec strange behaviour

#4 Post by foxidrive » 09 Mar 2016 03:31

That's interesting jeb! I tested the comspec here when commenting in that thread, and noticed that I had to change comspec twice before the expected issue showed itself. You delved further, when I just shrugged my shoulders. :D

Good work.

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

Re: ComSpec strange behaviour

#5 Post by penpen » 09 Mar 2016 10:04

The above lead me to the idea to create a "xx.bat":

Code: Select all

Z:\>> xx.bat echo %comspec% %*

Z:\>set comspec=xx

Z:\>echo Pipe | more

Z:\>C:\Windows\system32\cmd.exe /S /D /c" echo Pipe "
Pipe

Z:\>echo Pipe | more | more

Z:\>C:\Windows\system32\cmd.exe /S /D /c" echo Pipe "
Pipe


Z:\>(set comspec=xx&echo Pipe |more) | more
Der Befehl ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.

I was a liitle bit surprised, that the last command is executed in the actual cmd-instance (i thought they all are executed in a new task).
Second unexpected is, that the last command doesn't find xx.bat (even if i copy it to c:\windows\system32).
(And my hope to see, what the cmd shell executes on for /F was destroyed: just doesn't work even with xx.bat.)

penpen

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

Re: ComSpec strange behaviour

#6 Post by jeb » 10 Mar 2016 06:31

Hi penpen,

I suppose your results are a bit wrong
Your xx.bat look like

Code: Select all

echo C:\Windows\system32\cmd.exe %*

Instead of

Code: Select all

echo %comspec% %*


I modified xx.bat for more informations

Code: Select all

@echo off
setlocal DisableDelayedExpansion
set prompt=#
@echo ON
REM #### xx.bat startet ####
REM #### Content of %%0 : %0
REM #### Content of %%~0: %~0
REM #### Content of %%~f0: %~f0
REM #### %%*: '%*'
REM #### %%1: '%1'
REM #### %%2: '%2'
REM #### %%3: '%3'
REM #### %%4: '%4'
REM #### %%5: '%5'
@echo off
endlocal


I can't reproduce your last error, I simply get

Code: Select all

C:\temp>set comspec=xx

C:\temp>(set comspec=xx&echo Pipe |more) | more

#REM #### xx.bat startet ####

#REM #### Content of %0 : .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC

#REM #### Content of %~0: .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC

#REM #### Content of %~f0: C:\temp\xx.bat

#REM #### %*: '/S /D /c" ( set comspec=xx & echo Pipe | more )"'

#REM #### %1: '/S'

#REM #### %2: '/D'

#REM #### %3: '/c" ( set comspec=xx & echo Pipe | more )"'

#REM #### %4: ''

#REM #### %5: ''


It's interessting, that in %0 is garbage like 'COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC'

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

Re: ComSpec strange behaviour

#7 Post by penpen » 10 Mar 2016 08:06

jeb wrote:I suppose your results are a bit wrong
Your xx.bat look like

Code: Select all

echo C:\Windows\system32\cmd.exe %*

Instead of

Code: Select all

echo %comspec% %*
I checked my results with no error.
I guess you couldn't reproduce the error because there is no "echo" in my "xx.bat"; it only contains:

Code: Select all

C:\Windows\system32\cmd.exe %*


penpen

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

Re: ComSpec strange behaviour

#8 Post by jeb » 10 Mar 2016 12:12

Ok penpen, I missunderstood you completly :(

But to output some informations could be a good idea :idea:

If you change your xx..bat to

Code: Select all

@echo off
echo ComSpec '%~nx0' startet  > con
setlocal

set "prompt=$S"
(
@echo on
for %%a in (1) do REM ---| %* |--- REM
) > con
@echo off
echo Starting %%* now > CON
C:\Windows\system32\cmd.exe %*


Then you got for your last test
C:\temp>(set comspec=xx&echo Pipe |more) | more
ComSpec 'xx.bat' startet

REM ---| /S /D /c" ( set comspec=xx & echo Pipe | more )" |--- REM
Starting %* now
Der Befehl ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.


So the inner pipe creates the problem, when you build a second file by copy xx.bat "xx .bat"
Even this works

Code: Select all

C:\temp>(set comspec=xx&echo Pipe |more) | more
ComSpec 'xx .bat' startet

 REM ---| /S /D /c" ( set comspec=xx & echo Pipe | more )" |--- REM
Starting %* now
ComSpec 'xx .bat' startet

 REM ---| /S /D /c" echo Pipe " |--- REM
Starting %* now
Pipe


The only problem was that the `set comspec=xx &` creates 'comspec=xx<space>'

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

Re: ComSpec strange behaviour

#9 Post by penpen » 13 Mar 2016 08:45

Ah :oops:
I missed the extra space... .

jeb wrote:But to output some informations could be a good idea :idea:
Yes, so %0 is displayed in the error message ("Der Befehl "%0" ist entweder....").
Maybe this could be useful to know in future.

Btw:
jeb wrote:It's interessting, that in %0 is garbage like 'COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC'
This output made me create the xx.bat file:
Somehow the content of "PATHEXT" variable content is displayed (==the garbage).
But it seems it couldn't be used to start "xxyy.bat":

Code: Select all

Z:\>> xx.bat echo @echo xx.bat #  %* #  %~0

Z:\>set "pathext=yy.bat;%pathext%"

Z:\>set comspec=xx

Z:\>echo pipe|more
xx.bat #  /S /D /c" echo pipe" #  yy.bat;.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC

Z:\>> xxyy.bat echo echo xxyy.bat #  %* #  %~0

Z:\>echo pipe|more
Die Datei "Z:\xxyy.bat" kann nicht gefunden werden.
The error message is just a little bit irritating...
the file "Z:\xxyy.bat" couldn't be found only if it exists ... .


penpen

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

Re: ComSpec strange behaviour

#10 Post by npocmaka_ » 02 Jan 2018 17:37

looks like for /f presets the comspec (along with prompt and pathext) - https://stackoverflow.com/questions/480 ... environmen
and when comspec is not specified the pipe fails:

Code: Select all

set "comspec="
::this will print C:\WINDOWS\system32\cmd.exe
for /f %%a in ('echo %comspec%') do echo %%a
::this will crash the command window
break|break
COMSPEC , PROMPT and PATHEXT are interesting in other meanings too.
Looks COMSPEC changes are (in some degree) immideate and does not happen after the line/codeblock is finished

this will crash the command prompt:

Code: Select all

(

	set "comspec="
	echo %comspec%
	break|break
)
and this too:

Code: Select all

set "comspec=" & break|break

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

Re: ComSpec strange behaviour

#11 Post by penpen » 03 Jan 2018 04:34

The article from wdonahue (@stackoverflow) is a bit irritating.

You should get all variables set in:
- User Variables: HKEY_CURRENT_USER\Environment
- System Variables: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment

Has he cleared the "registry pre-setting", when he got this results?


penpen

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

Re: ComSpec strange behaviour

#12 Post by npocmaka_ » 03 Jan 2018 05:04

The script he's posted has the same behavior on my machine without changing anything in the registry - variables are "deleted" just for the current cmd session.

The interesting part is that the FOR /F starts a new instance of cmd (at least when an internal command is called) and it pre-sets PROMPT,COMSPEC and PATHEXT . But why only these three ( have no idea about the special variables like =:C and =:: ) ?

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

Re: ComSpec strange behaviour

#13 Post by jeb » 03 Jan 2018 06:20

It's strange.
The default values are only loaded, when the variable is undefined, not when it's only changed to another value.

And the pipe loads also the default values for PATHEXT and PATH.
For COMSPEC it fails, probably because COMSPEC is needed before the default load function is called.

I tested it with

Code: Select all

@echo off
setlocal EnableDelayedExpansion
FOR /F %%L in ('break') do echo Dummy to "cache" comspec

set var=pathext
echo Original value of %var% is "!%var%!"
echo(
call :test %var% ".com;.exe"
call :test %var% ""
exit /b


:test 
echo ------ set %1 to "%~2" ------
setlocal
set "%~1=%~2"
echo ******* Testing FOR /F ******* 
for /F "delims=" %%L in ('set %~1') do echo ###FROM FOR: %%L
echo(
echo ******* Testing PIP    ******* 
break | set %~1
echo(
exit /b

Post Reply