-> 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)
|