"Bad file name" Passing Command Line Parameters with RUN/CHAIN (73577)



The information in this article applies to:

  • Microsoft QuickBASIC 4.0
  • Microsoft QuickBASIC 4.0b
  • Microsoft QuickBASIC 4.5
  • 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 Q73577

SUMMARY

The RUN and CHAIN statements do not accept command line parameters. Attempting to add command line parameters after the filename for the RUN or CHAIN statement will result in run-time error 64, "Bad file name". (This error occurs for a program run in the QB.EXE (or QBX.EXE) development environment or as an .EXE program.) The inability to pass command line parameters with the RUN and CHAIN statements is a design limitation of Microsoft QuickBasic and Microsoft Basic Professional Development System (PDS).

A suggested method of passing command line parameters is to write the command line arguments to the Program Segment Prefix (PSP) of the resident program. When the RUN or CHAIN statement is executed, this information will be passed to the next program. Below is a description of how to write a command line to the Program Segment Prefix. Also below is an example program that passes a command line (or command string) between two Basic programs using the RUN statement.

This information applies to Microsoft QuickBasic versions 4.0, 4.0b and 4.5; Microsoft Basic Compiler versions 6.0 and 6.0a; Microsoft Basic PDS versions 7.0 and 7.1 for MS-DOS.

MORE INFORMATION

When a RUN or CHAIN statement is executed, the current command line contained within the Program Segment Prefix of the resident program is passed from the resident program to the RUN / CHAINed program. For this reason, you can change the command line contained within the PSP of the resident program directly, so that the RUN or CHAINed program will receive the new command line.

The command line can be changed by writing a new command line in the Program Segment Prefix (PSP) of the resident program. The segment address of the PSP can be found by calling DOS interrupt 21 hex with function 62 hex. The command line (also known as the command tail) within the PSP starts at offset 80 hex. The length of the command line is located at offset 80 hex followed by the command line itself starting at offset 81 hex. This is the format of the command line as understood by DOS. The command line as reported by COMMAND$ is stored in a different manner. The offset at 80 hex is treated as a pointer to the beginning of the command string. The Basic COMMAND$ function uses the value stored in the PSP at offset 80 to begin reading at the beginning of the command string and continue until a null character (CHR$(0)) is encountered.

Because all programs understand the DOS command line format, it is recommended that you read and write the command line in this format. If passing command line arguments to another Basic program, you will not be able to read the command line with COMMAND$. In order to read the command line, a routine that reads the command string from the PSP needs to be contained in the Basic program. This routine should be used in place of COMMAND$. The FUNCTION GetCommandLine$ in the code sample below is an example of a routine to read a DOS-formatted command line from the PSP.

Below is an example of passing a command line to another program. The programs read and write the command line in the DOS format using Basic procedures SetCommandLine and GetCommandLine$ respectively.

Code Example

COMM.BAS

DECLARE SUB SetCommandLine (CommandLine$)

'$INCLUDE: 'qb.bi'
DIM SHARED InRegs AS RegType, OutRegs AS RegType

'SetCommandLine does not preserve the command line held by COMMAND$.
'In the CALL statement below, COMMAND$ is passed along with the new
'command line arguments such that the original command line is not
'lost.
CALL SetCommandLine(COMMAND$ + "/Hi /There")

RUN "SHOWCOMM"

SUB SetCommandLine (CommandLine$)

     'Get the Program Segment Prefix for the program
     InRegs.AX = &H6200
     CALL interrupt(&H21, InRegs, OutRegs)
     PSPSegment% = OutRegs.BX

     'Set the segment to the Program Segment Prefix found above
     DEF SEG = PSPSegment%

     'The offset at location 80 hex within the PSP contains the length
     'of the command line.  Set it to the length of the command string
     'passed in.
     POKE &H80, LEN(CommandLine$)

     'Poke the command line into the PSP.  The command line within the
     'PSP always starts at offset 81 hex.
     FOR i% = 1 TO LEN(CommandLine$)
          POKE &H80 + i%, ASC(MID$(CommandLine$, i%, 1))
     NEXT i%

     'Put a NULL terminator (CHR$(0)) at the end of the command string.
     POKE &H80 + LEN(CommandLine$) + 1, 0

     DEF SEG
END SUB

DECLARE FUNCTION GetCommandLine$ ()
				

SHOWCOMM.BAS

'$INCLUDE: 'qb.bi'
DIM SHARED InRegs AS RegType, OutRegs AS RegType

CLS
PRINT GetCommandLine$
END

FUNCTION GetCommandLine$

        'Get the Program Segment Prefix for the program
        InRegs.AX = &H6200
        CALL interrupt(&H21, InRegs, OutRegs)
        PSPSegment% = OutRegs.BX

        'Set the segment to the Program Segment Prefix found above
        DEF SEG = PSPSegment%

        tmp$ = ""
        CommandLineLength% = PEEK(&H80)

        'PEEK the command line into a string.  Read characters until
        'a NULL character (CHR$(0)) is encountered or until the end
        'of the command line is reached.
        i% = 1
        WHILE i% <= CommandLineLength% AND PEEK(&H80 + i%) <> 0
                tmp$ = tmp$ + CHR$(PEEK(&H80 + i%))
                i% = i% + 1
        WEND

        DEF SEG

        GetCommandLine$ = tmp$

END FUNCTION
				

Modification Type:MinorLast Reviewed:8/16/2005
Keywords:KB73577