How do I get a recursive list of files in any simple way? Use the DOS "dir /A:-D /B /S" command.
How do I get my program to wait until the DOS prompt is finished before continuing without the extra code? Use the example I will provide in this simple FAQ.
The other day I posted a question for discussion that deals with figuring out how get a Visual Basic program to recursively list all the files in a directory and its subdirectories. We came across a couple painful solutions to it, and there was the ever-present DOS "dir" command. I figured that it's faster with that to get a list of files than with any of the other solutions, not to mention, less mind-boggling. My biggest problem was with the program not waiting for the command prompt to finish execution, which I found a simple, easy solution to as well. But anyways, here's my quick and easy solution: (I did this in VB6 under NT/2000 btw, but it should work basically the same in 95/98)
Objects you'll need: A Timer The VBA.FileSystem Objects
1. Global Variables You'll need a global variable or some variable to store a "ticker" for the timer which I will explain later.
In your Module1 (or where you put your global vars):
Global TimeTicker as numericaltype
Set numericaltype to Integer or Long if you don't know what to do about it.
2. The Form All you need to do here is put a new timer into the form, which will be our wait timer.
Set Timer1.interval = 1000* in it's properties (You may have to change this if the program you're running in DOS takes a long time before it puts output on the screen. *1000 = 1 second)
3. The Subroutines Your program only needs one routine for this operation, but if you want to or have to, you can split the code up a little.
First of all is the Timer. This is really easy. All you do is put this into the Timer1 routine:
Private Sub Timer1_Timer() TimerTicker = TimerTicker + 1 'If you don't plan on disabling the timer after the 'Routine is done with it, you will need to add the 'line below. This will prevent an overflow of the 'TimerTicker variable. If TimerTicker > 1000000 then TimerTicker = 0 End Sub
Next you will need a function to run until TimerTicker reaches a certain, specified value. Do so by doing this:
Private Sub WaitTimer (TimeWait) ' TimeWait, if the interval is set to 1000 will be ' in seconds. If so this will wait for about ' TimeWait seconds depending on when the ' function is called. Disabling the timer until use ' will make this run more accurately. Do Until TimeTicker >= TimeWait DoEvents Loop End Sub
Once you have that done you need to write a routine or function to run the DOS prompt and wait for the prompt to finish completely. To do this we have to have the program called from the command prompt to send itÆs output to a file. (Remember: I was writing this program to recursively retrieve a list of files underneath a certain directory and itÆs sub-directories) We will do this in a special way so that even when the command prompt is closed, it will not continue until all the data from the program is finished writing to a the file. If the program doesnÆt put data into a file very fast, you may have to increase the interval of the timer to compensate for the delays. HereÆs how I did this:
Private Sub Command1_Click () 'Disable the button until finished Form1.Command1.Enabled = False 'set our output file for the data from the prompt OutputFile = MyPath + ôfilename.txtö 'set the path of where we want the file list to 'start it's recursive listing. PathOfDirectory = ôc:\windows\ö
'First delete any old instance of the output file 'To safeguard any error, have the program rewrite 'the file which will make a new file if the file 'doesnÆt exist. Open OutputFile For Output As #99 Print #99, "Deleting" Close #99
'Delete the file. Kill OutputFile
'HereÆs a tricky part. This calls the command 'Prompt to run a program and exit when finished. 'Run a command prompt on your own time and type: ' for 95/98 users ôhelp commandö ' for NT/2k users ôhelp cmdö (or just use my ' example since itÆs done in NT/2k)
'put the command to be called by the shell in 'this variable below. The command I ran is: ' ôdir /A:-D /B /S [I]D:\Path\*.*[/I] 'This command will recursively list all the files 'in the directory and itÆs subdirectories and not 'the directory names (/A:-D = No directories) 'Putting the ô> ô+OutputFile at the end of the 'command will output to the OutputFile. ShellScript = "cmd /C dir /A:-D /B /S " + _ PathOfDirectory + "*.* > " + OutputFile
'Call the shell command Shell (ShellScript)
'Now wait here until an output file starts to be 'generated. Do 'Change 8 to whatever you want as long as it's 'greater than 0 If fs.FileExists(ProgramSettingsPath _ + "FileList.txt") And If FileLen _ (ProgramSettingsPath + "FileList.txt") _ > 8 Then Exit Do DoEvents Loop 'Now wait until the file doesnÆt change for a couple 'seconds. Since this is a ôdirö command, the output is 'instant and doesnÆt have any pauses in output. Change the 'wait timer to a larger number so that it waits longer 'before checking to see if there is more data being put in 'the file. OldLenOfFile = 0 Do DoEvents Call WaitTimer(2) Open OutputFile For Input As #111 DoEvents LenOfFile = LOF(111) 'check length of file. Close #111 If LenOfFile = OldLenOfFile Then Exit Do 'If there isnÆt anymore data, then exit
OldLenOfFile = LenOfFile Loop 'Add anything you want to run after the routine is 'over in here, or call another routine. End Sub
Add in anything at the end of the routine that you want and you're done. You can run the program and it will call a command prompt, write a list of the files or an output from a program you decided to use instead, and wait until the listing is done being written. Have fun!