TIP: Click on subject to list as thread! ANSI
echo: power_bas
to: ERIC SCHONNING
from: BRENT ASHLEY
date: 1995-06-04 22:36:00
subject: Re: Errorlevels

-> I have found the only way to return an errorlevel back into PB is to
-> execute the .exe or .com file in a batch file.  If you execute the
Interesting!  Sounds like a quirk that I wouldn't want to rely on,
though.  I wrote the following some time ago, which should work every
time with all versions of DOS.
'
' ErrShell.BAS
'
' - A great example of the power of inline assembler
'
' For EBA library by Brent Ashley
' 8 Nov 1993
'
' released to public domain
'
$INCLUDE "CONSTANT.INC"
$OPTION CNTLBREAK OFF
$INCLUDE "LibDecl.INC"
DEFINT A-Z
' exec parameter block for DOS EXEC call
TYPE EPBType
  Envir  AS WORD
  CmdOfs AS WORD
  CmdSeg AS WORD
  FCB1   AS DWORD
  FCB2   AS DWORD
END TYP
FUNCTION ErrShell?( CommandLine$ ) PUBLIC
  '
  ' Uses DOS EXEC function to call command.com
  ' with command string.  Avoids PB's annoying habit
  ' of losing cursor position on SHELL by updating
  ' PB cursor position to BIOS position after called program.
  '
  ' Also returns errorlevel of called program by monitoring
  ' int 12h svc 4ch and returning penultimate value (last
  ' value is returned by command.com itself)
  '
  ' Usage:  ErrorLevel? = ErrShell( CommandLine$ )
  DIM EPB AS EPBType
  ' find command.com
  Comspec$ = ENVIRON$("COMSPEC") + CHR$(0)
  ' set up command line to send to command.com
  Pgm$ = "/c " + CommandLine$ + " " + CHR$(13)
  CmdLen = LEN(Pgm$) - 1
  Pgm$ = CHR$(CmdLen) + Pgm$
  ' get ready to receive errorlevels
  OurCS?? = CODESEG(OurInt21)
  OurInt?? = CODEPTR(OurInt21)
  PenultOfs?? = CODEPTR(PenuErr)
  ' get and save current vector
  ! mov ax, &H3521
  ! int &H21
  ! mov cs:OldIntOfs, bx
  ! mov ax, es
  ! mov cs:OldIntSeg, ax
  ' point vector to our handler
  ! mov dx, OurInt??
  ! push ds
  ! mov ax, OurCS??
  ! mov ds, ax
  ! mov ax, &H2521
  ! int &H21
  ! pop ds
  ' make room for the exec shell
  dummy?? = SETMEM(-700000)
  ' set up exec parameter block
  EPB.Envir = 0
  EPB.FCB1 = 0
  EPB.FCB2 = 0
  EPB.CmdOfs = STRPTR(Pgm$)
  EPB.CmdSeg = STRSEG(Pgm$)
  ' set up registers and call exec function
  REG %DS, STRSEG(Comspec$)
  REG %DX, STRPTR(Comspec$)
  REG %ES, VARSEG(EPB)
  REG %BX, VARPTR(EPB)
  REG %AX, &H4B00
  CALL INTERRUPT(&H21)
  ' get penultimate errorlevel
  SaveSeg?? = pbvDefSeg
  DEF SEG = OurCS??
  ErrShell? = PEEK(PenultOfs??)
  DEF SEG = SaveSeg??
  ' clear data
  ! xor al, al
  ! mov cs:LastErr, al
  ! mov cs:PenuErr, al
  ' uninstall interrupt handler
  ! push ds
  ! mov dx, cs:OldIntOfs
  ! mov ax, cs:OldIntSeg
  ! mov ds, ax
  ! mov ax, &H2521
  ! int &H21
  ! pop ds
  ' fix cursor position
  SaveSeg?? = pbvDefSeg
  DEF SEG = 0
  LOCATE PEEK(&H451) + 1, PEEK(&H450) + 1
  DEF Seg = SaveSeg??
  ' restore far heap
  dummy?? = SETMEM(700000)
  EXIT FUNCTION
  ' our interrupt 21h handler
  OurInt21:
    ! cmp ah, &H4C
    ! je Svc4C
    ! jmp GotoOldInt
  ' if it's svc 4ch, save last 2 errorlevels
  Svc4C:
    ! push ax
    ! mov ah, cs:LastErr
    ! mov cs:PenuErr, ah
    ! mov cs:LastErr, al
    ! pop ax
  GotoOldInt:
    ! jmp dword ptr cs:OldIntPtr
  ' address of old interrupt 21h
  OldIntPtr:
  OldIntOfs:
    ! dw 0
  OldIntSeg:
    ! dw 0
  ' our data
  LastErr:
    ! db 0
  PenuErr:
    ! db 0
END FUNCTION
--- QScan/PCB v1.15b / 01-0348
---------------
* Origin: FidoNet: CRS Online, Toronto, Ontario (1:229/15)

SOURCE: echomail via exec-pc

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.