Hi all,
I'm trying to add a functionality to an existing program of mine so that it can delete folders, sub files and sub folders with their files.
For this I take it FindFirstFile and FindNextFile would be the best solution.
However, I'm a bit confused :dazzled: about the best solution for listing sub folders and their files.
Let's say I have the following folder structure:
C:\temp
C:\temp\test.txt
C:\temp\folder
C:\temp\folder\test1.txt
C:\temp\folder\folder2
C:\temp\folder\folder2\test2.txt
Since I do not know in advance how many sub folders will exist in the root folder and how many sub folder each sub folder has, etc.
How can I write a program which would list all of them, one by one, file by file, without having to create a huge amount of handles?
I have the following code already, which lists the files and folders from the root folder (C:\temp) perfectly, but after that I assume I would have to test each found file to see if it's a folder and if so, do the same thing all over again but with a different handle since I need to keep the original handle of the root folder to continue after I've finished with the subfolder.
Maybe I'm overlooking something, but I can't seem to get this fixed.
Here's the code:
.686
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
.DATA
mytestpath db 'C:\temp\*',0
nofile db 'Error: Invalid path specified.',0
myTitle db 'Folder Test',0
dot db '.',0
ddot db '..',0
.DATA?
mybuf db 512 dup (?)
wfd WIN32_FIND_DATA <>
hFind dd ?
.CODE
start:
invoke FindFirstFile, addr mytestpath, addr wfd
.IF eax==INVALID_HANDLE_VALUE
invoke MessageBoxA,NULL,addr nofile,addr myTitle,MB_ICONERROR
invoke ExitProcess,0
.ENDIF
mov hFind,eax
invoke lstrcmp,addr wfd.cFileName,addr dot
.IF eax!=0
invoke lstrcmp,addr wfd.cFileName,addr ddot
.IF eax!=0
invoke MessageBoxA,NULL,addr wfd.cFileName,addr myTitle,MB_OK
.ENDIF
.ENDIF
@@:
invoke FindNextFile,hFind,addr wfd
.IF eax!=0
invoke lstrcmp,addr wfd.cFileName,addr dot
.IF eax!=0
invoke lstrcmp,addr wfd.cFileName,addr ddot
.IF eax!=0
invoke MessageBoxA,NULL,addr wfd.cFileName,addr myTitle,MB_OK
.ENDIF
.ENDIF
jmp @B
.ENDIF
invoke FindClose,hFind
invoke ExitProcess,0
end start
The only thing I can think of is to create a recursive function. would this be the best solution?
Normally you use a recursive function to climb up and down directory trees, what may be the problem is to get it into the order you require as this method will display directories in the order they were created on disk.
Well, the order doesn't really matter, it was just an example.
The program securely deletes files, in what order, who cares :p
So a recursive function would be the best solution?
Basically yes, where you need to do some more woork is if any of the files are protected and must have their file attributes changed to archive first before you can delete them.
The attached file is my last play with this type of code. be careful and test it on a partition the has nothing useful on it as in its development where i was testing on a tail end partition, I managed to trash everything on the partition. I just forget where I left it as its been a few years since i have seen it.
[attachment deleted by admin]
If your only aim is to remove a folder and all of its contents, you can simply use the SHFileOperation function set to FO_DELETE
http://msdn.microsoft.com/en-us/library/bb762164.aspx
Thanks Hutch, I'll give it a close look ;)
@Tedd, it's not that easy. What I want is to be sure the files cannot be restored anymore, this means that we'll have to overwrite it several times manually.
I wrote a program with that functionality, works great, but only works for 1 file at the time.
So I want to add folders to it as well, hence the required function ;)
The recursive function that Hutch speaks of is very convenient (no, actually it's perfect), because if lets you easily delete your directory trees from bottom up. You have to delete from from bottom up, because you can't delete a directory until it is completely empty.
@Tedd, it's not that easy. What I want is to be sure the files cannot be restored anymore, this means that we'll have to overwrite it several times manually.
I thought that many softwares could delete file without the possibility of restore until I used the OnTrack software. Even with a good software like yours, I think that the file will be restored unless you fill all the disk...
Good dream...
The three programs included print out the name of all files in the current folder
and all sub-folders.
r1: Uses recursion, changes folders as it works, is the smallest code, slowest,
and uses most memory.
r2: Uses recursion, does not change folders while it works, is medium size and speed.
r3: Does not use recursion or change folders, is the largest and fastest, and
uses the least amount of memory while working.
And finally, a useful program.
r4: A routine written so you can call it repeatedly to get the next file name whenever
you need it. The example program just prints out the file name, but you could do
anything you wanted with the return.
[attachment deleted by admin]
Here http://www.idcat39.com/download/Bin/DirsAndFiles.exe is a program example for getting files list.
It uses a recursive algo.
This program comes with my own asm library but the research function is into a small file named "Search Files.asm".
The program generates two files : The first is used to store the directories found with an index. The second file is used to store the files names found. There is an index per file and an index on the directory into which there were found.
This program makes part of a program I have just began so it does not make a lot of things.
I have created a log window that you can use to store some actions for debugging.
Good luck
Now I remember why I stopped working on those routines-
This is simple, small, and really couldn't be any faster since most all of the execution time is taken up with actual disk access.
; from jimg
include \masm32\include\masm32rt.inc
.code
program:
.data
cmd2 db 'cmd /c dir "f:\*.asm" /s/w/b/a-d > ' ; the file specification wanted
dest2 db "r:allfile.txt",0
cmd3 db 'cmd /c dir "f:\*.*" /s/w/b/ad > ' ; to get all the folder names
dest3 db "r:allfold.txt",0
.code
invoke wshell,addr cmd2 ; get all the files
invoke wshell,addr cmd3 ; get all the folders
; that's it. really simple.
; example of reading the results
.data
aline dd 170 dup (0)
spos dd 0
answ dd 0
alen dd 0
lcnt dd 0
.code
invoke read_disk_file,addr dest2,addr answ,addr alen
.repeat
invoke readline,answ,addr aline,spos
mov spos,eax
inc lcnt
.until eax==0
invoke GlobalFree,answ
invoke wsprintf,addr aline,SADD("lines read=%li"),lcnt
invoke MessageBox,0,addr aline,0,0
invoke ExitProcess,eax
end program