home *** CD-ROM | disk | FTP | other *** search
- '─ Area: F-QUICKBASIC ─────────────────────────────────────────────────────────
- ' Msg#: 395 Date: 17 Apr 94 06:01:12
- ' From: Joe Negron Read: Yes Replied: No
- ' To: Larry Thacker Mark:
- ' Subj: Several questions
- '──────────────────────────────────────────────────────────────────────────────
- 'LT> I know that there is an area in memory from which you can get the
- ' > path of the program that is currently executing. How can I do it
- ' > with Quick BASIC? I've tried some crude memory searches, but they're
- ' > extremely slow and didn't give me what I was looking for. The
- ' > manual was no help.
-
- '----------------------------Begin PROGNAME.BAS-------------------------
- DEFINT A-Z
-
- '$INCLUDE: 'qb.bi' 'Needed for Interrupt calls
-
- DECLARE FUNCTION ProgramName$ ()
-
- '***********************************************************************
- '* FUNCTION ProgramName$
- '*
- '* PURPOSE
- '* Uses DOS ISR 21H, Function 51H (Get PSP Address) to return the
- '* name of the currently executing program. Note that this FUNCTION
- '* requires DOS 3.0 or >.
- '***********************************************************************
- FUNCTION ProgramName$ STATIC
- DIM Regs AS RegType 'Allocate space for TYPE
- ' RegType
- Regs.ax = &H5100 'DOS function 51h
- Interrupt &H21, Regs, Regs ' Get PSP Address
-
- DEF SEG = Regs.bx 'Regs.bx returns PSP sgmnt.
- EnvSeg% = PEEK(&H2C) + PEEK(&H2D) * 256 'Get environment address
- DEF SEG = EnvSeg% 'Set environment address
-
- DO
- Byte% = PEEK(Offset%) 'Take a byte
-
- IF Byte% = 0 THEN 'Items are ASCIIZ
- Count% = Count% + 1 ' terminated
-
- IF Count% AND EXEFlag% THEN 'EXE also ASCIIZ terminated
- EXIT DO 'Exit at the end
- ELSEIF Count% = 2 THEN 'Last entry in env. is
- EXEFlag% = -1 ' terminated with two
- Offset% = Offset% + 2 ' NULs. Two bytes ahead
- END IF ' is the EXE file name.
- ELSE 'If Byte% <> 0, reset
- Count% = 0 ' zero counter
-
- IF EXEFlag% THEN 'If EXE name found,
- Temp$ = Temp$ + CHR$(Byte%) ' build string
- END IF
- END IF
-
- Offset% = Offset% + 1 'To grab next byte...
- LOOP 'Do it again
-
- DEF SEG 'Reset default segment
- ProgramName$ = Temp$ 'Return value
- Temp$ = "" 'Clean up
- END FUNCTION
-
- 'LT> How can I read a directory and load the files into a table so I can
- ' > work on them? I've seen some crude methods where you redirect DIR
- ' > to a file and then read it, but I'd like to have a better way. Can
- ' > I read the directory directly?
-
- '========================== Begin LOADNAME.BAS ==========================
- DEFINT A-Z
-
- DECLARE SUB LoadNames (FileSpec$, Array$(), Attr%)
-
- DECLARE FUNCTION FileCnt% (FileSpec$, Attr%)
-
- '$INCLUDE: 'qb.bi' 'Needed for Interrupt call
-
- TYPE DTARec 'used by Find First/Next
- Reserved AS STRING * 21
- Attr AS STRING * 1
- NotNeeded AS STRING * 8 'Time/date/size (not needed)
- FileName AS STRING * 13
- END TYPE
-
- DIM SHARED DTA AS DTARec 'SHARED lets both FileCnt%()
- DIM SHARED RegsX AS RegTypeX ' and LoadNames access them.
- ' Use COMMON SHARED for access
- ' among multiple modules
- REDIM FileName$(1 TO 1) 'Create a dynamic arrray
-
- Spec$ = "C:\*.*"
-
- 'Note that this code does *not* return files with
- 'the Hidden, System, or Read-Only attributtes
- Attr% = 16 'Directories only
- Attr% = 32 'Files only
- Attr% = 48 'Files and Directories
- LoadNames Spec$, FileName$(), Attr%
-
- IF FileName$(1) = "" THEN
- PRINT "No matching files"
- ELSE
- FOR I% = 1 TO UBOUND(FileName$)
- PRINT USING "###: \ \"; I%; FileName$(I%)
- NEXT I%
- END IF
-
- END
-
- '***********************************************************************
- '* FUNCTION FileCnt%
- '*
- '* PURPOSE
- '* Uses DOS ISR 21H, Function 1AH (DOS set DTA Service), Function 4EH
- '* (Find First Matching Name), and Function 4FH (Find Next Matching
- '* Name) to obtain a count of files matching FileSpec$.
- '***********************************************************************
- FUNCTION FileCnt% (FileSpec$, Attr%) STATIC
- RegsX.dx = VARPTR(DTA) 'Set new DTA address
- RegsX.ds = -1 'DTA is in DGROUP
- RegsX.ax = &H1A00 'Set DTA
- InterruptX &H21, RegsX, RegsX 'Call DOS
-
- Count% = 0 'Initialize counter
-
- FBuff$ = FileSpec$ + CHR$(0) 'Needs to be ASCIIZ string
-
- RegsX.cx = Attr%
- RegsX.dx = SADD(FBuff$) 'FBuff$'s address
- RegsX.ds = -1 'For QB, sgmnt is always DGROUP
- RegsX.ax = &H4E00 'Find First Matching Name
-
- DO
- InterruptX &H21, RegsX, RegsX 'Call DOS
-
- IF RegsX.flags AND 1 THEN 'Error flag
- EXIT DO 'No more files
- END IF
-
- SELECT CASE Attr% 'Which attrs. are we to include?
- CASE 16 'Do we want to count only dirs?
- IF (ASC(DTA.Attr) \ 16) AND 1 THEN 'Is this one a directory?
- IF ASC(DTA.FileName) <> 46 THEN 'Ignore "." and ".."
- Count% = Count% + 1 'Found another dir name
- END IF
- END IF
- CASE 0, 32 'We only want to count files
- Count% = Count% + 1 'Found another file name
- CASE 48 'We want to count files & dirs
- Count% = Count% + 1
- END SELECT
-
- RegsX.ax = &H4F00 'Find next name service
- LOOP
-
- FileCnt% = Count% 'Assign value to function
- END FUNCTION
-
- '***********************************************************************
- '* SUB LoadNames
- '*
- '* PURPOSE
- '* Uses DOS ISR 21H, Function 1AH (DOS set DTA Service), Function 4EH
- '* (Find First Matching Name), and Function 4FH (Find Next Matching
- '* Name) to load the files matching FileSpec$ into an array.
- '***********************************************************************
- SUB LoadNames (FileSpec$, Array$(), Attr%) STATIC
- Spec$ = FileSpec$ + CHR$(0) 'Needs to be ASCIIZ string
-
- NumFiles% = FileCnt%(Spec$, Attr%) 'How many files match Spec$?
- IF NumFiles% = 0 THEN 'If there are none,
- EXIT SUB ' exit
- END IF
-
- REDIM Array$(1 TO NumFiles%) 'Allocate enough elements
-
- RegsX.dx = SADD(Spec$) 'the file spec address
- RegsX.ds = VARSEG(Spec$)
- RegsX.cx = Attr%
- RegsX.ax = &H4E00 'Find First Matching Name
-
- Count% = 0 'Initialize the counter
-
- DO
- InterruptX &H21, RegsX, RegsX 'Call DOS
- IF RegsX.flags AND 1 THEN 'Error flag
- EXIT DO 'No more files
- END IF
-
- Valid% = 0 'Assume invalid
-
- SELECT CASE Attr% 'Which attrs. are we to include?
- CASE 16 'Do we want to count only dirs?
- IF (ASC(DTA.Attr) \ 16) AND 1 THEN 'Is this one a directory?
- IF ASC(DTA.FileName) <> 46 THEN 'Ignore "." and ".."
- Valid% = -1 'Found another dir name
- END IF
- END IF
- CASE 0, 32 'We only want to count files
- Valid% = -1 'Found another file name
- CASE 48 'We want to count files & dirs
- Valid% = -1
- END SELECT
-
- IF Valid% THEN 'Add the file to array if
- Count% = Count% + 1 ' it's valid
- Z% = INSTR(DTA.FileName, CHR$(0)) 'Find terminating NUL
- Array$(Count%) = LEFT$(DTA.FileName, Z% - 1) 'assign the name
- END IF
-
- RegsX.ax = &H4F00 'Find Next Matching Name
- LOOP
- END SUB
-