call set bug?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Sponge Belly
Posts: 216
Joined: 01 Oct 2012 13:32
Location: Ireland
Contact:

call set bug?

#1 Post by Sponge Belly » 14 Nov 2015 15:10

Hello All! :)

Sorry I haven’t posted in a while. My mind has been… elsewhere. Anyways, could someone please explain what’s going on here?

Code: Select all

@echo off & setlocal enableextensions disabledelayedexpansion
set ^"str=  hello  ^&^"^&  world!  ^"
(call;)
call set "str1=%%str%%" && echo(success || echo(failure
set str
endlocal & goto :eof


The output says success, but str1 is not set. There is no error message and running the program with echo on sheds no light. Is there an explanation for this apparent contradiction… apart from overall Microsoft bugginess, that is? ;)

Laters!

- SB

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

Re: call set bug?

#2 Post by penpen » 14 Nov 2015 16:50

I don't know exactly (and actually i have no idea how to proof it), but I guess the "late expansion" of the doublequote confuses the "call"-command so that it recognizes the complete (command) string as a parameter of an empty command. The minimal example (under windows 8 ):

Code: Select all

@echo off
setlocal enableextensions disabledelayedexpansion
set doublequote="
call whatever "%%doublequote%%&"
endlocal
goto :eof


penpen

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

Re: call set bug?

#3 Post by jeb » 15 Nov 2015 05:19

It's a problem of special characters.

In a CALL statement unescaped special characters (&, |, &&, || ) droppes the complete command.
But this is only true for some characters, other characters like (<>) will be ignored.

Code: Select all

set "var1=#1 Visible > nul"
call echo %%var1%%

set "var2=#2 Invisible & echo Invisible"
call echo %%var2%%

set "var3=#3 Invisible || echo Invisible"
call echo %%var3%%


If you escape the special characters it works, you could also quote them.

Code: Select all

set "var4=#4 Visible ^> nul"
call echo %%var4%%

set ^"var5=#5 visible "&" visble"
call echo %%var5%%


But even here exists an exception, when the special character is the last character it works but without the special characters, too.

Code: Select all

set "var6=#6 Visible ||"
call echo %%var6%%

Sponge Belly
Posts: 216
Joined: 01 Oct 2012 13:32
Location: Ireland
Contact:

Re: call set bug?

#4 Post by Sponge Belly » 18 Nov 2015 14:59

Hi Penpen and Jeb! :)

Thanks for the explanations. Just one more pitfall to look out for when writing a Batch file! :twisted:

On a related topic, Jeb wrote in this post:

Code: Select all

set "safeSet=set^ ""
call %%safeSet%% var=123"


I was wondering why you didn’t just write:

Code: Select all

set "safeSet=set"
call %%safeSet%% "var=123"


Thanks in advance. ;)

- SB

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

Re: call set bug?

#5 Post by jeb » 18 Nov 2015 15:27

Sponge Belly wrote:On a related topic, Jeb wrote in this post:

Code:
set "safeSet=set^ ""
call %%safeSet%% var=123"

I'm impressed of this technic :D, as I forgot it completly and I reinvent the wheel this year, but this time my new technic was a bit more complex.

But now I try to answer your question
Sponge Belly wrote:I was wondering why you didn’t just write:

Code:
set "safeSet=set"
call %%safeSet%% "var=123"

The problem is that it starts a batch file named "set.bat" when it exists.

Even this fails

Code: Select all

set "safeSet=set^ "
call %%safeSet%% "var=123"

As now a file named "set<space>.bat" breaks the code.

Sponge Belly
Posts: 216
Joined: 01 Oct 2012 13:32
Location: Ireland
Contact:

Re: call set bug?

#6 Post by Sponge Belly » 21 Nov 2015 04:53

Hi Jeb,

Ah, now I get it! :idea:

The weird syntax is to guard against the unlikely event that a user has a file called "set.bat" or "set<Space>.bat" on his/her PATH. :twisted:

However did you think to check for that? :o

And one last thing, you said:

I reinvent the wheel this year, but this time my new technic was a bit more complex.


Which technique are you referring to?

Cheers! :)

- SB

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

Re: call set bug?

#7 Post by jeb » 21 Nov 2015 09:57

Sponge Belly wrote:Which technique are you referring to?

Ah, sorry I forgot to show it

Code: Select all

(SET LF=^
%EMPTY_LINE%
)
set var=orig
set "SAFESET=^^!LF!!LF!set"
call %%SAFESET%% "var=hello"
set var


And btw I retested the old solution and it fails!

Code: Select all

set "safeSet=set^ ""
call %%safeSet%% var=123"

When a file named "set<space><space>var=123.bat" exists it tries to start it

I suppose my new solution seaches for a file named "<linefeed>set.bat", but that should be more or less safe, as this a uncommon name :wink:
Or perhaps a file named "" (empty) is searched ...

Sponge Belly
Posts: 216
Joined: 01 Oct 2012 13:32
Location: Ireland
Contact:

Re: call set bug?

#8 Post by Sponge Belly » 22 Nov 2015 11:01

Hi Jeb, :)

Thanks for the explanation, but I think I’ll stick with Dave Benham’s icall macro if I ever find myself in a situation where I’m forced to make extensive use of call set.

Cheers!

- SB

trebor68
Posts: 146
Joined: 01 Jul 2011 08:47

Re: call set bug?

#9 Post by trebor68 » 23 Nov 2015 05:03

I have the code from the first Postin changed somewhat.

Code: Select all

@echo off
setlocal enableextensions disabledelayedexpansion
set ^"str=  hello  ^&^"^&  world!  ^"
echo CALL ^&^& echo(success ^|^| echo(failure
call && echo(success || echo(failure
echo.
echo.
echo (CALL) ^&^& echo(success ^|^| echo(failure
(call) && echo(success || echo(failure
echo.
echo.
echo (CALL;) ^&^& echo(success ^|^| echo(failure
(call;) && echo(success || echo(failure
echo.
echo.
echo CALL set "str1=%%%%str%%%%" ^&^& echo(success ^|^| echo(failure
call set "str1=%%str%%" && echo(success || echo(failure
echo.
echo.
echo call (SET "str1=%%%%str%%%%" ^&^& echo(success ^|^| echo(failure
call (set "str1=%%str%%" && echo(success || echo(failure
echo.
set str
endlocal & goto :eof


Here the output:

Code: Select all

D:\CMDVerz>test66
CALL && echo(success || echo(failure
success


(CALL) && echo(success || echo(failure
failure


(CALL;) && echo(success || echo(failure
success


CALL set "str1=%%str%%" && echo(success || echo(failure
success


call (SET "str1=%%str%%" && echo(success || echo(failure
failure

str=  hello  &"&  world!

D:\CMDVerz>


The first command to the CALL command follows another character (space). The CALL command is executed correctly.

In the second command the CALL command follows no other sign. The CALL command can not be executed correctly.

The third command the CALL command follows another character (semicolon). The CALL command is executed correctly.

The fourth command the CALL command follows a complete command. The CALL command is executed correctly.

The fifth command the CALL command follows an open parenthesis. Everything what comes after the opening parenthesis is running as an independent command (SET command). The SET command is not correctly carried out (reason: Number of quotes).

Post Reply