Pass errorlevel from one batch file to another?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: Pass errorlevel from one batch file to another?

#16 Post by sambul35 » 19 Jun 2016 16:59

Assuming without testing, there might be a difference in ascending order, why I don't see any difference in descending order results from higher to lower errorlevel? It shouldn't matter - or it should? Now I guess it should, since higher errorlevel values would be processed earlier if exist.
Last edited by sambul35 on 19 Jun 2016 17:02, edited 1 time in total.

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Pass errorlevel from one batch file to another?

#17 Post by aGerman » 19 Jun 2016 17:01

Assuming without testing

Just try it.

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

Re: Pass errorlevel from one batch file to another?

#18 Post by foxidrive » 22 Jun 2016 13:03

Clueless in Seattle wrote:MS-DOS 6.21 installed on my machine


Will, can you launch a command with dosshell running

Code: Select all

mem /d >\ds.txt

and then exit dosshell completely and launch this

Code: Select all

mem /d >\nods.txt

and then paste the contents of both files into a message, along with your \config.sys file contents?

I'm thinking that the free memory in your system may be able to be improved.

douglas.swehla
Posts: 75
Joined: 01 Jun 2016 09:25

Re: Pass errorlevel from one batch file to another?

#19 Post by douglas.swehla » 25 Jun 2016 11:31

Clueless in Seattle wrote:I'd like to add a line at the very beginning of file #2 like this:

Code: Select all

if errorlevel 0 goto end

The objective would be that if file #1 returns an errorlevel of 0, then there would be no need to even run file # 2.


Your two basic approaches are to
  1. have a parent file decide to run batch2.bat based on the outcome of batch1.bat, or
  2. have batch1.bat decide to run batch2.bat based on the outcome of a command in batch1.bat.
It's possible for batch2.bat to skip to the end like you suggest, but it makes more sense to decide that earlier and not bother launching the script if it doesn't need to run.

Option 1:

Code: Select all

:: Parent file (batch0.bat?) decides whether to run batch2.bat.
call batch1.bat || call batch2.bat


Option 2:

Code: Select all

:: Batch1.bat has been launched by parent file.
:: Batch1.bat decides whether to run batch2.bat.
cmd1
cmd2
cmd3 || call batch2.bat


In Option 1, we're assuming that cmd3 is the last command run in batch1.bat, so that its ERRORLEVEL gets returned to the parent batch. For both options, it's the success or failure of cmd3 that is the basis of the decision.

These suggestions rely on conditional execution and the CALL command, both of which should work in actual DOS (command.com):
http://www.robvanderwoude.com/condexec.php
http://www.robvanderwoude.com/call.php

Edit: It turns out that the conditional syntax used above does not work in DOS or older Windows versions (COMMAND.COM). Fortunately, as described in the first link, these symbols are just shorthand for code we can write out in a slightly longer format. So, while that tactic doesn't work in DOS, the strategy is still legit. I'm going to leave this comment in place for any NT and later Windows users that stumble across this, and post a modified version separately.

The first link above goes over conditional execution, but I'll review in a bit more detail. In the explanations below, "succeeds" means "returns an ERRORLEVEL of 0", and "fails" means "returns an ERRORLEVEL of anything but 0"

Code: Select all

:: A) One ampersand: Run cmd1, and then always run cmd2 (barring catastrophic failure, of course)
cmd1 & cmd2

:: B) Two ampersands: Run cmd1, and then, if and only if cmd1 succeeds, run cmd2.
cmd1 && cmd2

:: C) One pipe char: Send the output (stdout stream) of cmd1 to the input (stdin stream) of cmd2.
:: This has nothing to do with success or failure, I'm just including it for completeness.
cmd1 | cmd2

:: D) Two pipe chars: Run cmd1, and then, if and only if cmd1 fails, run cmd2.
cmd1 || cmd2

:: E) Combine B and D. Run cmd1, and then either cmd2 (if success) or cmd3 (if failure).
:: Actually, cmd3 runs if cmd2 fails, and cmd2 only fails if cmd1 fails. Which is why...
cmd1 && cmd2 || cmd3

:: F) ...reversing the order of E doesn't work the way you might expect.
:: We want to run cmd2 if cmd1 succeeds, but with this order, it only runs if cmd3 succeeds,
:: and cmd3 only runs if cmd1 fails, meaning cmd2 only runs if cmd1 fails, which is
:: the opposite of what we want.
cmd1 || cmd3 && cmd2


The convenience of this approach is that we needn't worry about testing exact ERRORLEVEL values or the order in which they're tested, as in the IF ERRORLEVEL or CHOICE approaches. Since ERRORLEVEL is either "0" or "not 0", we're working with a real either/or, true/false scenario.

As always, if you post the actual code you're running, and the output you're hoping for, we can help you better.
Last edited by douglas.swehla on 09 Jul 2016 18:40, edited 1 time in total.

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

Re: Pass errorlevel from one batch file to another?

#20 Post by penpen » 25 Jun 2016 13:24


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

Re: Pass errorlevel from one batch file to another?

#21 Post by foxidrive » 26 Jun 2016 14:38

douglas.swehla wrote:These suggestions rely on conditional execution and the CALL command, both of which should work in actual DOS (command.com):
http://www.robvanderwoude.com/condexec.php
http://www.robvanderwoude.com/call.php


I've just read some recent posts you've written in your clear and expressive way. Welcome to Dostips douglas, as all new arrivals are welcome.

I just wanted to comment that my experience has shown me that the conditional execution was introduced in the NT line of Windows, so MSDOS can't do it.

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

Re: Pass errorlevel from one batch file to another?

#22 Post by penpen » 26 Jun 2016 17:48

foxidrive wrote:I just wanted to comment that my experience has shown me that the conditional execution was introduced in the NT line of Windows, so MSDOS can't do it.
Confirmed: I've just tested it.

The ampersand character ('&') is just a normal character in (my) MS-DOS 6.22,
two pipe characters ("||") results in a "Syntax error.".
Only a single pipe character ('|') works as expected.


penpen

douglas.swehla
Posts: 75
Joined: 01 Jun 2016 09:25

Re: Pass errorlevel from one batch file to another?

#23 Post by douglas.swehla » 09 Jul 2016 18:52

foxidrive wrote:I've just read some recent posts you've written in your clear and expressive way. Welcome to Dostips douglas, as all new arrivals are welcome.

Thanks! Happy to be here.

foxidrive wrote:I just wanted to comment that my experience has shown me that the conditional execution was introduced in the NT line of Windows, so MSDOS can't do it.

Umm, are you sure?

penpen wrote:Confirmed: I've just tested it.

Well, shoot.

Thanks for catching and testing that, guys. I've edited the original post, and will add a modified one with the corrections.

A new concern is, does COMMAND.COM set ERRORLEVEL according to the same rules as CMD.EXE? Please see the new post for a full explanation of the problem.

douglas.swehla
Posts: 75
Joined: 01 Jun 2016 09:25

Re: Pass errorlevel from one batch file to another?

#24 Post by douglas.swehla » 09 Jul 2016 19:13

So, my last answer used syntax that doesn't work in DOS, which was a chief requirement. This answer is an attempt to fix that.

Clueless in Seattle wrote:I'd like to add a line at the very beginning of file #2 like this:

Code: Select all

if errorlevel 0 goto end

The objective would be that if file #1 returns (passes to file # 2) an errorlevel of 0, then there would be no need to even run (all but the first command in) file # 2.


It's possible for file #2 to skip to the end like you suggest, but it makes more sense to test the outcome of the relevant command in file #1, and based on that, decide whether to launch file #2 at all.

Your two basic approaches are to
  1. have parent.bat decide to run child2.bat based on the outcome of the last command in child1.bat, or
  2. have child1.bat decide to run child2.bat based on the outcome of the last command before the decision point in child1.bat.

In both cases, the intent is that the decision to call child2.bat is based on the outcome of cmd3, the last command in child1.bat.

In each code snippet below, the first example should* work in both modern Windows (using CMD.EXE) and in older Windows and DOS (using COMMAND.COM),
while the second relies on newer syntax introduced with Windows NT (CMD.EXE only).

Option 1:

Code: Select all

:: We are in parent.bat, which decides whether to run child2.bat,
:: depending on outcome of last command run in child1.bat.
:: Assumes ERRORLEVEL behavior is same in CMD.EXE and COMMAND.COM.

rem Windows and DOS syntax:
call child1.bat
if errorlevel 1 call child2.bat

rem Windows-only equivalent:
call child1.bat || call child2.bat

exit


Option 2:

Code: Select all

:: We are in child1.bat, which has been called by parent.bat.
:: Batch file child1.bat decides whether to call child2.bat.

rem First part of batch is same for both, we only care about cmd3:
cmd1
cmd2

rem Windows and DOS syntax:
cmd3
if errorlevel 1 call child2.bat

rem Windows-only equivalent:
cmd3 || call child2.bat

exit


*Option 1 may actually not work in DOS, depending on how COMMAND.COM determines ERRORLEVEL. In CMD.EXE, immediately after a called batch file exits and returns control to the caller, the ERRORLEVEL indicates the success of the last command run in the called batch, rather than the success of the CALL command itself. Option 1 relies on this fact, so if the behavior is not the same in COMMAND.COM, it won't work. I don't have a copy of COMMAND.COM to test with, so anybody who does is welcome to weigh in on that.

Option 2, as far as I can tell, is bulletproof.

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

Re: Pass errorlevel from one batch file to another?

#25 Post by foxidrive » 10 Jul 2016 07:34

I'm confirming here that Option 1 does work in MSDOS.

See pic: http://imgur.com/TRl8XK1

Option 2 will work as you've said


The only exception is where the command or program doesn't return an errorlevel.

douglas.swehla
Posts: 75
Joined: 01 Jun 2016 09:25

Re: Pass errorlevel from one batch file to another?

#26 Post by douglas.swehla » 10 Jul 2016 15:54

foxidrive wrote:I'm confirming here that Option 1 does work in MSDOS.

Excellent, thanks!

foxidrive wrote:The only exception is where the command or program doesn't return an errorlevel.

Good point. In that case, the simplest solution is probably to just check the command result, e.g., did the file get created/moved/deleted, or did the drive get mapped/mounted, or whatever, and then call the next batch only if it didn't happen.

Post Reply