• Please review our updated Terms and Rules here

Errorlevels Codes in the DOS Batch process

Agent Orange

Veteran Member
Joined
Sep 24, 2008
Messages
6,651
Location
SE MI
I resurrected my old DOS batch menu program (compliments: Van Wolvernton "Supercharging DOS (c) 1986) with the intention of updating it a little bit. Basically what it does is let you gallivant around your PC via a batch file which holds a nice little menu. For example, If I wanted to quit the menu program and return to DOS, I would press the F10 key to exit.

:GET_RPLY
reply
if errorlevel 68 goto F10
:F10
cls
goto END
:END


The errolevels for the menu program are 59 through 69 which denotes F1 to F10 with errorlevel 69 sending it back to :Get_RPLY. The input is held by a small program called reply.com, which may be easily assembled through DEBUG. My problem is that I wish to to expand the menu to use F11 and F12 keys. Neither of those two function keys trap as you would expect. My question is does anyone know how to get an errorlevel return from the F11 and F12 keys.
 
Last edited:
F11 should be 0x85 and F12 0x86... which works out to 133 and 134 decimal... Reply just returns the scancodes, so errorlevel 133 should get you F11.


I like the list in the Free Pascal docs because it resembles the one from the back of all the old Turbo manuals I must have photocopied several dozen times the past two and a half or so decades. It's in Hex, but that's easy enough to convert.

http://www.freepascal.org/docs-html/rtl/keyboard/kbdscancode.html

You might also want to read the microsoft page about it since it includes how to handle multi-key and advanced scancodes.

http://support.microsoft.com/kb/77457
 
F11 should be 0x85 and F12 0x86... which works out to 133 and 134 decimal... Reply just returns the scancodes, so errorlevel 133 should get you F11.


I like the list in the Free Pascal docs because it resembles the one from the back of all the old Turbo manuals I must have photocopied several dozen times the past two and a half or so decades. It's in Hex, but that's easy enough to convert.

http://www.freepascal.org/docs-html/rtl/keyboard/kbdscancode.html

You might also want to read the microsoft page about it since it includes how to handle multi-key and advanced scancodes.

http://support.microsoft.com/kb/77457

Thanks for the reply but I think there may be some confusion between scan codes and batch errrolevels. I'm going to try and bone up the subject through the MS knowledge base.
 
Thanks for the reply but I think there may be some confusion between scan codes and batch errrolevels. I'm going to try and bone up the subject through the MS knowledge base.
Try COMMAND /Z

AFAIK DOS only provides 255 errorlevel return codes and I'm not sure if that includes F11 and F12, but worth a try.
 
In your REPLY program, note how errorlevel 68 corresponds to the F10 key. 68 decimal is 44 hex.

Below is a partial table of key scan codes. The XT code for the F10 key is 44 hex.
So your REPLY program appears to be putting the XT scan code into the AL register for use by 'errorlevel' functionality.

If that is the case, it follows that the errorlevel to use for the F11 key is 87, and for the F12 key is 88.

xt_scancode_f11_f12.jpg
 
Thanks for the reply but I think there may be some confusion between scan codes and batch errrolevels. I'm going to try and bone up the subject through the MS knowledge base.
If you check the article I linked to, and it's corresponding ASM -- it pulls using the same DOS routine programs like turbo pascal does with it's readkey -- INT 21 function 08 -- input from console without echo. The first number should actually be ASCII 7 bit, if it is zero then it's an extended scancode, throws that value away and then returns -- the extended scancode. UNFORTUNATELY this means that extended codes are reported as other characters, which can be... problematic. (be better if it could store two values somehow). Look at the ASM:

Code:
xxxx:0100   MOV AH,08   Get character input without echo
xxxx:0102   INT 21      Perform MS-DOS service
xxxx:0104   CMP AL,0    Compare AL with zero
xxxx:0106   JNZ 010A    If lead zero, get second code of character
xxxx:0108   INT 21      Perform MS-DOS service
xxxx:010A   MOV AH,4C   Terminate process with return code
xxxx:010C   INT 21      Perform MS-DOS service

Honestly, I'd consider gutting that down to:

Code:
MOV AH,08
INT 21
MOV AH,4C
INT 21

Because it's int21 AH08, it will wait for the keyboard to have something, so a 'successful' result of 0 would actually mean there's an extended keycode waiting.

:ask
reply
if errorLevel 0 goto extendedCodes
REM process normal scancodes here
goto ask
:extendedCodes
REM process extended scancodes here
goto ask

The two "goto ask" being for when it drops through unhandled.

And again, because it's Int 21 AH 08, what it will give you is IDENTICAL to what turbo pascals readkey would... a non-extended code being the actual ASCII that's currently typed, the extended code being for non-standard keys that don't map to ASCII.

Which is why the table I linked to on the FPC website is the correct one. That you are getting 59...68 for F1 through F10 -- 3B through 44 hex, bears this out. Check it. It's also why using their reply.com typing any of these ":;<=>?@ABCD" will respond as F1 through F10 -- because theirs doesn't pass the 0 as the marker for an extended scancode.

I mean, the source code to implement readkey in Turbo Pascal for DOS is just:
Code:
function readkey:char; assembler;
asm
	mov ah,$08
	int $21
end;

-- edit --
Oh, and the above has a flaw, you'd want to store the errorlevel since "if errorlevel" will in fact act as true for any value equal to or higher than the value you check against.... major pain in the ass in some cases. If errorLevel 0 would always be true; if errorlevel 68 is true for 69, 70, etc, etc...

-- edit edit --

Found it, this guys article explains that better:
http://www.robvanderwoude.com/errorlevel.php
 
Last edited:
Taking the errorlevel quirks into account, using the 'gutted' reply.com code I posted above that does not discard 0, this would trap F1 through F12, AND ESC -- without mistaking other keys for the function keys.

Code:
:ask
reply
if errorlevel 28 goto ask
if errorlevel 27 goto end
if errorlevel 1 goto ask
reply
if errorlevel 135 goto ask
if errorlevel 134 goto F12
if errorlevel 133 goto F11
if errorlevel 69 goto ask
if errorlevel 68 goto F10
if errorlevel 67 goto F9
if errorlevel 66 goto F8
if errorlevel 65 goto F7
if errorlevel 64 goto F6
if errorlevel 63 goto F5
if errorlevel 62 goto F4
if errorlevel 61 goto F3
if errorlevel 60 goto F2
if errorlevel 59 goto F1
goto ask
 
... and do you one even better -- here's a working demo:
http://www.cutcodedown.com/for_others/agentOrange/batchdemo.rar

I called the .com file 'readkey' instead of 'reply' so as to show that it's different -- and as I suspected it can detect F1 through F10 and ESC, without mistaking any other keys for the extended ones; something 'reply.com' cannot.

... and you know, it's probably been over two decades since I made a COM file using debug... old school hardcore. As before the code for readkey.com ended up:

MOV AH,08
INT 21
MOV AH,4C
INT 21

Resulting in a whopping 14 byte .COM file.

Hope that helps. Now all you need is a ISR to trap ^C -- since you can't trust "break off" to actually work.
 
In your REPLY program, note how errorlevel 68 corresponds to the F10 key. 68 decimal is 44 hex.

Below is a partial table of key scan codes. The XT code for the F10 key is 44 hex.
So your REPLY program appears to be putting the XT scan code into the AL register for use by 'errorlevel' functionality.

If that is the case, it follows that the errorlevel to use for the F11 key is 87, and for the F12 key is 88.

xt_scancode_f11_f12.jpg

Logically thinking you would be correct but it doesn't happen that way. There doesn't seem to be an errorlevel that returns the F11 or F12 key (been there - done that). If you think about it, the F10 and F11 keys were 'newcomers" in the early going.
 
Taking the errorlevel quirks into account, using the 'gutted' reply.com code I posted above that does not discard 0, this would trap F1 through F12, AND ESC -- without mistaking other keys for the function keys.

Code:
:ask
reply
if errorlevel 28 goto ask
if errorlevel 27 goto end
if errorlevel 1 goto ask
reply
if errorlevel 135 goto ask
if errorlevel 134 goto F12
if errorlevel 133 goto F11
if errorlevel 69 goto ask
if errorlevel 68 goto F10
if errorlevel 67 goto F9
if errorlevel 66 goto F8
if errorlevel 65 goto F7
if errorlevel 64 goto F6
if errorlevel 63 goto F5
if errorlevel 62 goto F4
if errorlevel 61 goto F3
if errorlevel 60 goto F2
if errorlevel 59 goto F1
goto ask

Is this your code for ASK?


function readkey:
char; assembler; asm

mov ah,$08
int $21 end;
 
Last edited:
Why don't you just try the following:

INVOKE REPLY

In other words, execute the program "INVOKE" with "REPLY" as command line argument (assuming that both programs can be found via the PATH environment variable). INVOKE would in-turn execute REPLY, wait until it terminates and then display the result code (AKA error code) returned by REPLY. Repeating this procedure a couple of times, once for each of the F1 to F10 keys, two more times for F11 and F12 and perhaps some more times for any other keys, you could very easily know which codes your REPLY returns for the various keys, if any.

You find the program INVOKE (those who read here more frequently might already guess it :) ) as part of the DOSUTILS package, which can be downloaded from here: http://www.bttr-software.de/products/jhoffmann/
 
... and do you one even better -- here's a working demo:
http://www.cutcodedown.com/for_others/agentOrange/batchdemo.rar

I called the .com file 'readkey' instead of 'reply' so as to show that it's different -- and as I suspected it can detect F1 through F10 and ESC, without mistaking any other keys for the extended ones; something 'reply.com' cannot.

... and you know, it's probably been over two decades since I made a COM file using debug... old school hardcore. As before the code for readkey.com ended up:

MOV AH,08
INT 21
MOV AH,4C
INT 21

Resulting in a whopping 14 byte .COM file.

Hope that helps. Now all you need is a ISR to trap ^C -- since you can't trust "break off" to actually work.

Your code doesn't work. Seems to be a problem with 'AH'. P.S. I am not a programmer, but I did survive a college level course in BASIC and Assembly a long, long time ago.
 
Your code doesn't work. Seems to be a problem with 'AH'. P.S. I am not a programmer, but I did survive a college level course in BASIC and Assembly a long, long time ago.
It works (although it's only 8 bytes long, not 14) but it doesn't return the extended codes you're looking for.

Here's a step by step debug session to create a program that does (although as DS noted you will have duplications, i.e. non-extended keys returning the same code as the extended keys):
http://support.microsoft.com/kb/77457

But these routines just generate the error code as your REPLY.COM does; you still need some way to display them if you're testing, like COMMAND /Z or Juergen's INVOKE. If your REPLY.COM program generates them, then 133 and 134 are the errorlevels you should be testing for F11 and F12.
 
Last edited:
I don't know what you're on about with it not working if you're using the contents of that RAR file. The included batch file and testkey.com reply exactly as expected here in virtualbox, dosbox, on a sharp PC7000 and my tandy 1000HX.

You MOV AH,08, INT 21, AL now contains next keycode or zero for extended... call AH,4C INT 21 to exit using AL as that code...

Tested working DOS 6.22, DOS 3.3 and even in a CMD under Win98.

Screencap of the contents of that rar running in DOSBOX

http://www.cutcodedown.com/for_others/agentOrange/dosbox.png

Works just fine.... and it's 14 bytes since you have the overhead of a COM file... if you have a 8 byte version, you did something wrong, or whatever you are unpacking that rar with goofed.

TO BUILD IT YOURSELF:

Code:
C:\batch>[COLOR="#B22222"]debug[/COLOR]
-[COLOR="#B22222"]A 100[/COLOR]
1165:0100 [COLOR="#B22222"]MOV AH,08[/COLOR]
1165:0102 [COLOR="#B22222"]INT 21[/COLOR]
1165:0104 [COLOR="#B22222"]MOV AH,4C[/COLOR]
1165:0106 [COLOR="#B22222"]INT 21[/COLOR]
1165:0108
-[COLOR="#B22222"]rcx[/COLOR]
CX 0000
:[COLOR="#B22222"]e[/COLOR]
-[COLOR="#B22222"]n TESTKEY.COM[/COLOR]
-[COLOR="#B22222"]w[/COLOR]
Writing 000E bytes
-[COLOR="#B22222"]q[/COLOR]
C:\batch>

Yes, it's 000E bytes because that's the minimum file size of a .COM! I put the parts you type in red.

With the batch file EXACTLY as I wrote it: -- edit -- I'm adding comments
Code:
@echo off
echo Press F1 through F10 or ESC to exit
:read
REM read first keycode
readkey

REM at this point it is either the ASCII that was typed, or zero for an extended keycode...
REM so A would be 65, SPACE is 32, ESC is 27, etc, etc... 

REM greater than or equal 28, loop to read again
if errorlevel 28 goto read

REM is 27 (escape) exit batch
if errorlevel 27 goto end

REM is greater than or equal to 1, loop to read again
if errorlevel 1 goto read

REM if it drops to here, first code was zero so read extended code!
readkey

REM at this point errorlevel contains an extended keycode

REM >= 135 loop, we don't care about those
if errorlevel 135 goto read

if errorlevel 134 goto F12
if errorlevel 132 goto F11

REM >= 69, loop to start as well, we don't want those
if errorlevel 69 goto read

REM Do I really need to comment these?!?
if errorlevel 68 goto F10
if errorlevel 67 goto F9
if errorlevel 66 goto F8
if errorlevel 65 goto F7
if errorlevel 64 goto F6
if errorlevel 63 goto F5
if errorlevel 62 goto F4
if errorlevel 61 goto F3
if errorlevel 60 goto F2
if errorlevel 59 goto F1

REM drops to here, must be 0..58, so loop 
goto read

REM begin handlers

:F12
echo You Pressed F12
goto read
:F11
echo You Pressed F11
goto read
:F10
echo You Pressed F10
goto read
:F9
echo You Pressed F9
goto read
:F8
echo You Pressed F8
goto read
:F7
echo You Pressed F7
goto read
:F6
echo You Pressed F6
goto read
:F5
echo You Pressed F5
goto read
:F4
echo You Pressed F4
goto read
:F3
echo You Pressed F3
goto read
:F2
echo You Pressed F2
goto read
:F1
echo You Pressed F1
goto read

:end
echo You Pressed ESC, Exiting

WORKS JUST GREAT. If it's not working for you, you're not doing what I'm saying, using the pre-built RAR, or have a broken unpacker.

Pay attention to how there are TWO readkey in it -- the first for non-extended ASCII returns, the second when the first code is zero handles extended keycodes!
 
Last edited:
Back
Top