You are not logged in.

#1 09 Feb 2016 00:32

kiwipaulw
New Member
Registered: 08 Feb 2016
Posts: 4

Call batchC ( chain batchD ) gives unexpected result

Hi,

SS64 gives the best detail on batch file operation I've found - but I've been caught by a behavior that I haven't seen explained on any website:

If I have a batch file b.bat that calls another (c.bat)
and in c.bat I have a chain to d.bat,
then on completion of d.bat I expect execution to continue in b.bat just after the call to C.bat.

That does work, exactly as expected, unless in c.bat the chain to d.bat occurs within parentheses, such as within an if clause extended over several lines.  In this case the behaviour becomes a bit weird.
In my Win7 testing, it seems as if on completion of d.bat execution sort of continues with the remainder of the code in parentheses in c.bat before returning to the expected location in b.bat after the call.  Perhaps particular code in parentheses after the chain command is non-functional as I originally had a goto label that never found the perfectly good label that was in c.bat and worked in other circumstances.

My point here is that I can't find which of the rules of batch file programming I've broken, having tried to locate such a rule on SS64 and other places.

Files that demonstrate this issue are:
b.bat

@echo We are in B
@echo call to C
pause
call C
@echo Back in B again after call to C has returned
pause

c.bat

@echo We got to C
pause
if Pope==Pope (
  @echo within parentheses in C
  @echo chain to D
  D
  @echo we do NOT expect to end up back here in C in parentheses
)
@echo we do NOT expect to end up back here in C 
pause

d.bat

@echo we got to D
@echo exiting D
pause

Yes - there are other ways of structuring things.  I deliberately chose this way because I have an a.bat that launches b.bat in a new window inheriting the environment variables of a.bat - but I need to have an "exit" command to close the window and that is best placed at the end of b.bat.  The line I have in a.bat is:

start "First part of a nice window title" /MAX b Optional trailing title shown after the batch name

I would like to see somewhere on SS64 that tells me the above code isn't going to work correctly.

Offline

#2 09 Feb 2016 14:44

foxidrive
Member
Registered: 04 Apr 2013
Posts: 339

Re: Call batchC ( chain batchD ) gives unexpected result

You might find that it's not quite what you thought it was - if the loop is significant.


b.bat

@echo off
echo Begin B
echo calling C.bat
call C
echo Back in B
pause

c.bat

@echo off
echo Begin C
D
echo End C

d.bat

@echo off
echo Begin D
echo End D

Last edited by foxidrive (09 Feb 2016 14:44)

Offline

#3 09 Feb 2016 20:52

kiwipaulw
New Member
Registered: 08 Feb 2016
Posts: 4

Re: Call batchC ( chain batchD ) gives unexpected result

foxidrive: I'm not sure what you are referring to as 'the loop'.  My point is that the parentheses (used in the if statement) cause unexpected behaviour.

For me, your example, without parentheses, yields exactly as one would expect:

Begin B
calling C.bat
Begin C
Begin D
End D
Back in B
Press any key to continue . . .

Running my example (which has the chain command within a block enclosed by parentheses) modified to your style (adding @echo off and removing all but one pause) yields the following unexpected result (tested under Win7 professional):

We are in B
call to C
We got to C
within parentheses in C
chain to D
we got to D
exiting D
we do NOT expect to end up back here in C in parentheses
Back in B again after call to C has returned
Press any key to continue . . .

Offline

#4 10 Feb 2016 02:51

Aacini
Member
Registered: 05 Dec 2012
Posts: 149

Re: Call batchC ( chain batchD ) gives unexpected result

This is a simplified version of your code:

b.bat:

@echo off
echo We are in B, calling  C
call C
echo Back in B after call to C has returned

c.bat:

@echo off
echo We are in C
(
  echo Within parentheses in C, chaining to D
  D
  echo Within parentheses in C, after D ends
)
echo After parentheses in C

d.bat:

echo We are in D
echo Terminating D

And this is the output:

We are in B, calling  C
We are in C
Within parentheses in C, chaining to D
We are in D
Terminating D
Within parentheses in C, after D ends
Back in B after call to C has returned

In c.bat the line with just the "D" invoke d.bat without CALL command. When I explain this mechanism I used to say: "at this point d.bat replaces the execution of c.bat"; this means that when d.bat terminate, supposedly c.bat should end at same point. However, as your code proves, if the line that invoke d.bat is placed in a code block, then the lines already parsed in such block are executed after d.bat ends, and only after such block terminate the c.bat itself ends. This is certainly an unexpected behavior that I can not explain.

If an EXIT /B is inserted in d.bat the behavior is the same. However, if d.bat is terminated via a plain EXIT (no /B) command, then the whole cmd.exe session is terminated at that point, as expected.

Offline

#5 10 Feb 2016 03:59

RG
Member
From: Minnesota
Registered: 18 Feb 2010
Posts: 362

Re: Call batchC ( chain batchD ) gives unexpected result

Aacini's explanation explains most of it and the behavior makes sense. There are likely better explanations... but here is mine. There are a couple of key things in play here:
1. In one case you are calling another bat file... which means you will come back to where you left off.
2. In the other case you are simply executing another bat without a CALL and if that execution is launched from a non-parenthesized section of code you don't come back to that location.
But if that code is executed from a section of code in parentheses the execution comes back to the next line. The reason is this:
The entire parenthesized block of code is loaded as one entity... regardless of the number of lines.  So the line:

echo Within parentheses in C, after D ends

Is already loaded before we execute D when it appears in the parenthesized block.
That code is NOT yet loaded when we execute D in a non-parenthesized block of code.
Hope that helps.


Windows Shell Scripting and InstallShield

Offline

#6 10 Feb 2016 22:49

foxidrive
Member
Registered: 04 Apr 2013
Posts: 339

Re: Call batchC ( chain batchD ) gives unexpected result

kiwipaulw wrote:

foxidrive: I'm not sure what you are referring to as 'the loop'.

My mistake, I meant the command within parenthesis.

My point is that the parentheses (used in the if statement) cause unexpected behaviour.

If I change c.bat to this then the behaviour is exactly the same.

@echo off
echo Begin C
if Pope==Pope (
  D
)
echo End C

Are you launching D.bat and expecting it to terminate all scripts when it finishes?

That's why someone would launch a batch script without a call keyword, and it's unclear to me what you are doing.

Offline

#7 11 Feb 2016 02:32

kiwipaulw
New Member
Registered: 08 Feb 2016
Posts: 4

Re: Call batchC ( chain batchD ) gives unexpected result

foxidrive wrote:

Are you launching D.bat and expecting it to terminate all scripts when it finishes?
That's why someone would launch a batch script without a call keyword, and it's unclear to me what you are doing.

kiwipaulw wrote:

If I have a batch file b.bat that calls another (c.bat)
and in c.bat I have a chain to d.bat,
then on completion of d.bat I expect execution to continue in b.bat just after the call to C.bat.

The script I was originally trying to write is not the reason for this posting.  I posted this because the documented behaviour of windows batch scripts at ss64.org disagrees the observed behaviour.

When I read ss64.com/nt/syntax-brackets.html I would expect to be told something along the lines of (this is my first guess at appropriate wording):
"Chaining to another batch file from within parentheses can produce unpredictable or unexpected results.  Within parentheses, always use Call to invoke another batch file."

Reasons for suggesting that wording are anomalies I've noted in the following cases:
1. Call to batch file - (parentheses in called batch file containing chain followed by echo).
2. Call to batch file - (parentheses in called batch file containing chain followed by echo then goto LabelExistingOutSideParentheses).
3. (parentheses in a batch file containing chain followed by echo).  Note that this is the same as my first example without b.bat.
4. (parentheses in a batch file containing chain followed by echo then goto LabelExistingOutSideParentheses).
5. ((2 levels of parentheses in a batch file with chain as last command in inner parentheses) followed by echo in outer parentheses).
The pattern I'm seeing is that any chain to another batch file from within parentheses doesn't do what you would expect - i.e. it doesn't stop parenthesised code in the existing batch file from executing.

Offline

#8 11 Feb 2016 11:55

jeb
Member
From: Germany
Registered: 19 Nov 2010
Posts: 109

Re: Call batchC ( chain batchD ) gives unexpected result

The results aren't unpredictable, if you know the rules.

It's always a bad idea to start a second batch without CALL, independent of parenthesis.
As this mechanism is broken (it can call an unexpected label).

The content of blocks will be cached (in RAM) always.
This cache can't be modified and it can only be stopped by executing a 'goto :label'

Offline

#9 11 Feb 2016 22:43

kiwipaulw
New Member
Registered: 08 Feb 2016
Posts: 4

Re: Call batchC ( chain batchD ) gives unexpected result

jeb wrote:

The results aren't unpredictable, if you know the rules.

I can see that the strict interpretation of 'unpredictable' does not agree with German expectations of precision.  I guess the rules are just too complex for me consider it worthwhile bothering to make a prediction.  Feel free to suggest better wording.  It is a long time since I worked in your nice country.

jeb wrote:

It's always a bad idea to start a second batch without CALL, independent of parenthesis.
As this mechanism is broken (it can call an unexpected label).

I've been using batch files since the pre-Windows era (probably before CALL was added) and I've never come across this advice - not even on SS64 pages.  Where can I get further detail on the problem and advice you describe?

I will assume 'broken' is an imprecise way of saying the results are hard to predict. wink

Offline

#10 12 Feb 2016 01:51

foxidrive
Member
Registered: 04 Apr 2013
Posts: 339

Re: Call batchC ( chain batchD ) gives unexpected result

kiwipaulw wrote:

the results are hard to predict. wink

That, my friend, is the perfect way to describe the behaviour of batch code. smile


This sites forum is filled with the idiosyncrasies of batch commands and also the odd things that can happen when they are chained together.
http://www.dostips.com

People find more and more creative ways to use the odd things that happen, and that is what makes batch coding enjoyable for me. smile

Last edited by foxidrive (12 Feb 2016 01:51)

Offline

#11 12 Feb 2016 19:09

Simon Sheppard
Admin
Registered: 27 Aug 2005
Posts: 1,130
Website

Re: Call batchC ( chain batchD ) gives unexpected result

I have just updated the page with some notes about this
Things that break inside parenthesis
http://ss64.com/nt/syntax-brackets.html

If you execute a second batch file without using CALL you may run into some buggy behaviour: if both batch files contain a label with the same name and you have previously used CALL to jump to that label in the first script, you will find execution of the second script starts at the same label. Even if the second label does not exist this will still raise an error "cannot find the batch label". This bug can be avoided by always using CALL.
http://ss64.com/nt/call.html

Offline

Board footer

Powered by