Microsoft KB Archive/71234

= B_ONEXIT Is Not Always Automatic in QB.EXE or QBX.EXE; Restart =

Article ID: 71234

Article Last Modified on 11/21/2006

-

APPLIES TO


 * Microsoft QuickBasic 4.0
 * Microsoft QuickBASIC 4.0b
 * Microsoft QuickBasic 4.5 for MS-DOS
 * Microsoft BASIC Compiler 6.0
 * Microsoft BASIC Compiler 6.0b
 * Microsoft BASIC Professional Development System 7.0
 * Microsoft BASIC Professional Development System 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 &quot;binding&quot; 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.

Assembler 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 &quot;Use the Open option on the File Menu&quot; PRINT &quot;to lose all keyboard input.&quot; 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.

Additional query words: QuickBas BasicCom buglist4.00 buglist4.00b buglist4.50

Keywords: KB71234

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.