B_ONEXIT Is Not Always Automatic in QB.EXE or QBX.EXE; Restart (71234)
The information in this article applies to:
- Microsoft QuickBASIC 4.0
- Microsoft QuickBASIC 4.0b
- Microsoft QuickBASIC 4.5
- Microsoft BASIC Compiler for MS-DOS and OS/2 6.0
- Microsoft BASIC Compiler for MS-DOS and OS/2 6.0b
- Microsoft Basic Professional Development System for MS-DOS 7.0
- Microsoft Basic Professional Development System for MS-DOS 7.1
This article was previously published under Q71234 SYMPTOMS
B_ONEXIT is a system-level Basic function designed to allow non-Basic
routines in your program to take special actions when the Basic
program ends. B_ONEXIT works as expected at the termination of Basic
executable .EXE programs.
Note that the Basic run-time routine B_ONEXIT is not automatically
invoked when your program ends if you are running inside the QB.EXE or
QBX.EXE environment. B_ONEXIT is only invoked by the environment if
you restart your program. This is correct behavior because the
environment needs to maintain the final state of the program in case
you want to view variable values or use the History debugging
features.
However, after running a program, the QB.EXE or QBX.EXE environment
fails to invoke B_ONEXIT when you perform an Open or New command from
the File menu.
STATUS
Microsoft has confirmed this to be a bug in QB.EXE in Microsoft QuickBasic
versions 4.00, 4.00b, and 4.50; in the QB.EXE environment that comes with
Microsoft Basic Compiler versions 6.00 and 6.00b for MS-DOS (buglist6.00,
buglist6.00b); and in the QBX.EXE (QuickBasic Extended) environment that
comes with Microsoft Basic Professional Development System (PDS) versions
7.00 and 7.10 for MS-DOS (buglist7.00, buglist7.10). We are researching
this problem and will post new information here in the Microsoft Knowledge
Base as it becomes available.
MORE INFORMATION
In the QuickBasic environment, your program does not actually
terminate by the END or SYSTEM statements, but instead, terminates
when you perform an operation that requires QuickBasic's "binding"
process to be invoked. Operations, such as major changes to the code
(where QuickBasic prompts you with an optional restart message) or
loading a new program, cause the old program to terminate, and then
QuickBasic binds the new program.
The QuickBasic environment fails to call B_ONEXIT when you choose
operations from the File menu (such as Open or New). As a workaround
to ensure that B_ONEXIT is called consistently, you need to manually
choose the Restart option from the Run menu immediately after the
termination of your program in QB.EXE or QBX.EXE.
The following example uses an assembly routine to install a new
keyboard interrupt vector and uses B_ONEXIT to restore the old
keyboard interrupt when the program ends. When the following program
is executed inside the QuickBasic environment and you perform a Load
operation from the File menu after running the program, the program
will terminate but B_ONEXIT will not be invoked, and the keyboard will
be disabled. To correct the problem, you will either have to
restart/reboot the computer, or use the mouse to select the Restart
option from the Run menu, which will invoke B_ONEXIT and restore the
keyboard interrupt.
This example shows a simple case of what could happen when B_ONEXIT is
not called. The actual results will be unpredictable, depending on
your code.
The following code samples were provided by a customer reporting the
problem and are shown here as examples.
Code ExampleAssembler Code (INT9.ASM)
.model medium, basic
EXTRN B_OnExit:FAR ; in the QBX/BC run time
.code
OldInt9 LABEL DWORD ; Old Keyboard interrupt vector
Old9Ofs dw 0 ; handler address.
Old9Seg dw 0
Int9Restore PROC uses ds
; Auto-restore the vectors we may have changed. Registered with
; _onexit.
cmp Old9Seg, 0 ; did we get the vector
jz @f ; No, lets jump to the return
mov ax, 2509H ; otherwise, we restore the vector
lds dx, OldInt9
INT 21H
mov Old9Seg, 0 ; and clear our old vector
@@: ret
Int9Restore ENDP
Int9Grabber PROC
; Gets the original INT9 vector in case we change it during processing
cmp Old9Seg, 0 ; already have it?
jnz @f ; yes, don't set it twice
; and lets jump to the return
mov ax, 3509H
INT 21H
mov Old9Seg, es ; we are just going to chain
mov Old9Ofs, bx ; the int9 through our own
; handler.
mov ax, offset @code:Int9Restore
push cs
push ax
call B_OnExit ; register the restore routine
@@: ret
Int9Grabber ENDP
END
Basic Code (Basic.BAS)
DEFINT A-Z
DECLARE SUB Int9Grabber ()
Int9Grabber ' Install Int9 handler, if not already installed
CLS
PRINT "Use the Open option on the File Menu"
PRINT "to lose all keyboard input."
END
Build Options
MASM INT9.ASM;
LINK /Q INT9.OBJ,,,BQLB40.LIB;
QB Basic.BAS /L INT9.QLB
BQLB40.LIB will be replaced by the appropriate Quick-library support
module for the version of the product being used.
Modification Type: | Minor | Last Reviewed: | 8/16/2005 |
---|
Keywords: | KB71234 |
---|
|