Examples of Loading MS-DOS Directory Listing into an Array (41447)



The information in this article applies to:

  • Microsoft Visual Basic for MS-DOS
  • 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 (PDS) for MS-DOS and MS OS/2 7.0
  • Microsoft Basic Professional Development System (PDS) for MS-DOS and MS OS/2 7.1

This article was previously published under Q41447

SUMMARY

This article discusses three different methods of putting an MS-DOS disk directory listing into a string array.

Example 1 demonstrates how to use the DIR$ function to read a directory listing into an array. This is probably the simplest method for use with Visual Basic for MS-DOS. The DIR$ functions was introduced in Microsoft Basic PDS for MS-DOS and MS OS/2, version 7.0. For an example of using the DIR$ function (which works in both MS-DOS and MS OS/2), query the Knowledge Base on the following keywords:

7.0 and "DIR$" and DIRECTORY and LISTING

Example 2 shows a simple method to SHELL to the MS-DOS DIR command, redirect the output to a file, and input from the file into string variables.

Example 3 below shows how to load an MS-DOS disk directory listing into a string array, using the CALL INTERRUPT statement to invoke the MS-DOS operating-system Interrupt 21h, with functions 1Ah (SetDTA), 4Eh (FindFirst), and 4Fh (FindNext).

MORE INFORMATION

For an example of calling the MS-DOS interrupt functions to obtain disk directory information in Microsoft QuickBasic for MS-DOS, versions 2.0, 2.01, or 3.0, query the Knowledge Base on the following keywords:

INT86.OBJ and FINDFIRST

For a Microsoft Basic PDS for MS-DOS and MS OS/2, version 7.0 or 7.1 or Microsoft Basic Compiler for MS-DOS and MS OS/2, version 6.0 or 6.0b example that displays directory information in MS OS/2 protected mode, query the Knowledge Base on the following keywords:

DosFindFirst or DosFindNext

Example 1

' To try this example in VBDOS.EXE:
' 1. From the File menu, choose New Project.
' 2. Copy the code example to the Code window.
' 3. Press F5 to run the program.
DEFINT A-Z
CONST TRUE = -1
CONST FALSE = NOT TRUE
NumFiles = 255             ' Maximum number of filenames to hold.
Counter = 0
Finished = FALSE
DIM FileName$(NumFiles)

CLS     ' Enter DIR type filespec, for example "C:\*.BAS":
INPUT "Enter filespec:"; Path$
TempName$ = DIR$(Path$)             ' Get the first filename.
IF TempName$ = "" THEN
  PRINT "No file(s) found"
ELSE
  FileName$(Counter) = TempName$ ' Keep getting filenames until we
  Counter = Counter + 1          ' have NumFiles worth or we get
  DO                             ' them all.
    TempName$ = DIR$
    IF TempName$ <> "" THEN FileName$(Counter) = TempName$
    Counter = Counter + 1
  LOOP WHILE TempName$ <> "" AND Counter <= NumFiles
END IF
IF FileName$(0) <> "" THEN    ' Display filenames if we received
  Counter = 0                 ' any.
  DO
    PRINT FileName$(Counter)
    IF FileName$(Counter) = "" THEN Finished = TRUE
    Counter = Counter + 1
  LOOP WHILE Counter <= NumFiles AND NOT Finished
END IF
END
				

Example 2

' To try this example in VBDOS.EXE:
' 1. From the File menu, choose New Project.
' 2. Copy the code example to the Code window.
' 3. Press F5 to run the program.
'
' This example works in QuickBasic for MS-DOS, versions 2.0, 2.01, 3.0,
' 4.0, 4.0b, and 4.5; and Basic Compiler for MS-DOS and MS OS/2,
' versions 6.0 and 6.0b; and Basic PDS for MS-DOS and MS OS/2,
' versions 7.0 and 7.1.

nf = 200   ' Handles directory listing up to 200 lines.
DIM buffer$(nf)
INPUT "Enter Search Path: ", path$   ' Enter path such as c:
SHELLSTRING$ = "dir " + path$ + " >dirfile.dat"
SHELL SHELLSTRING$   ' SHELL to the MS-DOS DIRectory command.
OPEN "dirfile.dat" FOR INPUT AS #1
pntr% = 0
WHILE NOT EOF(1) AND pntr% < nf
  pntr% = pntr% + 1
  INPUT #1, buffer$(pntr%)  ' Inputs one directory line at a time.
  PRINT buffer$(pntr%)
WEND
CLOSE #1
KILL "dirfile.dat"
END
				

Example 3

' To try this example in VBDOS.EXE:
' 1. From the File menu, choose New Project.
' 2. Copy the code example to the Code window.
' 3. Press F5 to run the program.

' To run this program in the environment, you must invoke the
' environment with the /L switch to load the default Quick library:
'    VBDOS.EXE /L          for Visual Basic 1.0 for MS-DOS

' Use the following include file for Visual Basic 1.0 for MS-DOS:
REM $INCLUDE: 'VBDOS.BI'
' This examples works in QuickBasic for MS-DOS, versions 4.0, 4.0b,
' and 4.0; and Basic Compiler for MS-DOS and MS OS/2 (real mode only),
' versions 6.0 and 6.0b.

' Use the following include file for QuickBasic for MS-DOS:
REM $INCLUDE: 'QB.BI'

TYPE FileFindBuf
      dos            AS STRING * 21
      Attributes     AS STRING * 1
      CreateTime     AS INTEGER
      AccessDate     AS INTEGER
      FileSize       AS LONG
      FileName       AS STRING * 13
END TYPE
TYPE FileInfo
      FileName       AS STRING * 13
      Size           AS STRING * 8
      Seconds        AS STRING * 4
      Minutes        AS STRING * 4
      Hours          AS STRING * 4
      Day            AS STRING * 4
      Month          AS STRING * 4
      Year           AS STRING * 5
END TYPE
DIM BUFFER AS FileFindBuf
DIM FileInfoBlock(100) AS FileInfo
DECLARE SUB intbuf (BUFFER AS FileFindBuf)
DECLARE SUB setdta (BUFFER AS FileFindBuf)
DECLARE FUNCTION firstfm! (path$, fa%)
DECLARE FUNCTION nextfm ()
DECLARE SUB CalculateAssign (FileInfoBlock() AS ANY, BUFFER AS ANY,_
                             counter!)
DECLARE SUB PrintDirList (FileInfoBlock() AS ANY, i!)
CLS : CALL setdta(BUFFER)
INPUT "Enter the files spec: "; path$
fa% = 0  ' A value of 16 includes directory names.
counter = 0
IF (firstfm(path$, fa%) = 0) THEN
  DO
   counter = counter + 1
   CalculateAssign FileInfoBlock(), BUFFER, counter
   CALL setdta(BUFFER)
  LOOP WHILE (nextfm = 0)
END IF

CLS
FOR i = 1 TO counter
   PrintDirList FileInfoBlock(), i
NEXT i

END

SUB CalculateAssign (FileInfoBlock() AS FileInfo, _
                     BUFFER AS FileFindBuf, counter)
   FileInfoBlock(counter).FileName = BUFFER.FileName
   FileInfoBlock(counter).Size = STR$(BUFFER.FileSize)
   FileInfoBlock(counter).Seconds = STR$(BUFFER.CreateTime AND &H1F)
   FileInfoBlock(counter).Minutes = _
              STR$((BUFFER.CreateTime AND &H7E0) \ 32)
   ' If BUFFER.CreateTime is negative add 64K to make unsigned integer:
   IF BUFFER.CreateTime < 0 THEN
     FileInfoBlock(counter).Hours = _
              STR$(((BUFFER.CreateTime + 2 ^ 16) AND &HF800) \ 2048)
   ELSE
     FileInfoBlock(counter).Hours = _
              STR$((BUFFER.CreateTime AND &HF800) \ 2048)
   END IF
   FileInfoBlock(counter).Day = STR$(BUFFER.AccessDate AND &H1F)
   FileInfoBlock(counter).Month = _
              STR$((BUFFER.AccessDate \ 32) AND &HF)
   FileInfoBlock(counter).Year = _
              STR$((BUFFER.AccessDate \ 512) + 1980)
END SUB

FUNCTION firstfm (path$, fa%)
  DIM inreg AS regtypeX, outreg AS regtypeX
' Use regtype for QuickBasic.
  inreg.ax = &H4E00
  inreg.cx = fa%
  FileName$ = path$ + CHR$(0)
  inreg.dx = SADD(FileName$)
  inreg.ds = SSEG(FileName$)
' Use CALL INTERRUPT in QuickBasic for MS-DOS.
  CALL INTERRUPTX (&H21, inreg, outreg)
  firstfm = (outreg.ax AND &HF)
END FUNCTION

SUB intbuf (BUFFER AS FileFindBuf) STATIC
' The first 20 bytes are reserved for MS-DOS and are unchanged.
    BUFFER.CreateTime = 0
    BUFFER.Attributes = " "
    BUFFER.AccessDate = 0
    BUFFER.FileSize = 0
    BUFFER.FileName = STRING$(13, 32)
END SUB

FUNCTION nextfm
  DIM inreg AS regtype, outreg AS regtype
  inreg.ax = &H4F00
  CALL interrupt(&H21, inreg, outreg)
  nextfm = outreg.ax AND &HF
END FUNCTION

SUB PrintDirList (FileInfoBlock() AS FileInfo, i)
  PRINT FileInfoBlock(i).FileName;
  PRINT SPACE$(5); FileInfoBlock(i).Size;
  PRINT SPACE$(5); RTRIM$(LTRIM$(FileInfoBlock(i).Month)) + "-";
  IF LEN(RTRIM$(LTRIM$(FileInfoBlock(i).Day))) = 1 THEN
    FileInfoBlock(i).Day = "0" + LTRIM$(FileInfoBlock(i).Day)
  END IF
  PRINT RTRIM$(LTRIM$(FileInfoBlock(i).Day)) + "-";
  PRINT RTRIM$(LTRIM$(FileInfoBlock(i).Year));
  IF VAL(FileInfoBlock(i).Hours) = 0 THEN
    FileInfoBlock(i).Hours = STR$(12) ' Change midnight from 0 to 12.
  END IF
  IF VAL(FileInfoBlock(i).Hours) > 12 THEN
    x% = VAL(FileInfoBlock(i).Hours) - 12
    FileInfoBlock(i).Hours = STR$(x%)
    suffix$ = "p"
  ELSE
    suffix$ = "a"
  END IF
  IF VAL(FileInfoBlock(i).Hours) = 12 AND_
                      VAL(FileInfoBlock(i).Minutes) > 0 THEN
    suffix$ = "p"
  END IF
  IF LEN(RTRIM$(LTRIM$(FileInfoBlock(i).Hours))) = 1 THEN
    t% = 7
  ELSE
    t% = 6
  END IF
  PRINT SPACE$(t%); RTRIM$(LTRIM$(FileInfoBlock(i).Hours)) + ":";
  IF LEN(RTRIM$(LTRIM$(FileInfoBlock(i).Minutes))) = 1 THEN
    FileInfoBlock(i).Minutes = "0" + LTRIM$(FileInfoBlock(i).Minutes)
  END IF
  PRINT RTRIM$(LTRIM$(FileInfoBlock(i).Minutes));
  PRINT suffix$
END SUB

SUB setdta (BUFFER AS FileFindBuf) STATIC
  DIM inreg AS regtypex, outreg AS regtypex
  CALL intbuf(BUFFER)
  inreg.ax = &H1A00
  inreg.ds = VARSEG(BUFFER)
  inreg.dx = VARPTR(BUFFER)
  CALL interruptx(&H21, inreg, outreg)
END SUB
				

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