Pass errorlevel from one batch file to another?
Moderator: DosItHelp
Re: Pass errorlevel from one batch file to another?
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.
Re: Pass errorlevel from one batch file to another?
Assuming without testing
Just try it.
Re: Pass errorlevel from one batch file to another?
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.
-
- Posts: 75
- Joined: 01 Jun 2016 09:25
Re: Pass errorlevel from one batch file to another?
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
- have a parent file decide to run batch2.bat based on the outcome of batch1.bat, or
- have batch1.bat decide to run batch2.bat based on the outcome of a command in batch1.bat.
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.
Re: Pass errorlevel from one batch file to another?
This may help you on MS-DOS 6.22 (untested):
http://alt.msdos.batch.narkive.com/FBsOd3wY/reset-set-and-display-get-errorlevel.
penpen
http://alt.msdos.batch.narkive.com/FBsOd3wY/reset-set-and-display-get-errorlevel.
penpen
Re: Pass errorlevel from one batch file to another?
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.
Re: Pass errorlevel from one batch file to another?
Confirmed: I've just tested it.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.
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
-
- Posts: 75
- Joined: 01 Jun 2016 09:25
Re: Pass errorlevel from one batch file to another?
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.
-
- Posts: 75
- Joined: 01 Jun 2016 09:25
Re: Pass errorlevel from one batch file to another?
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.
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
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:
Option 2:
*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.
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
- have parent.bat decide to run child2.bat based on the outcome of the last command in child1.bat, or
- 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.
Re: Pass errorlevel from one batch file to another?
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.
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.
-
- Posts: 75
- Joined: 01 Jun 2016 09:25
Re: Pass errorlevel from one batch file to another?
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.