Есть функция, которая находит и удаляет все файлы в указанной директории Код (Text): pathanymask db "\*",0 LOCAL WFD:WIN32_FIND_DATA invoke SetCurrentDirectory,ADDR fullpathfordelete invoke lstrcat,addr fullpathfordelete,addr pathanymask invoke FindFirstFile,addr fullpathfordelete,addr WFD cmp eax,INVALID_HANDLE_VALUE je exit mov hFind,eax deleting: invoke FindNextFile,hFind,addr WFD test eax,eax jz exit invoke DeleteFile,addr WFD.cFileName jmp deleting exit: invoke FindClose,hFind Как находить и удалять файлы во вложенных папках? Насколько я понимаю, после нахождения очередного элемента каталога проверяем установлен ли бит FILE_ATTRIBUTE_DIRECTORY в поле WFD.dwFileAttributes, если установлен, то начинаю проверять этот элемент, дальше... захожу в тупик. Может у кого есть подходящий "кусочек" кода (masm32)? SHFileOperation не подходит.
vg Сделай функцию, которая удаляет все файлы в указанном ей каталоге, а потом рекусивно вызывает себя из каждого подкаталога.
Ну вот например (написано очень давно, поэтому за стиль не пинать ): Код (Text): .data ThisDirectory db ".",0 SearchMask db "\*",0 Slash db "\",0 .code scan_directory PROC Directory:PBYTE LOCAL FindData:WIN32_FIND_DATA, SearchFilter[MAX_PATH]:byte, CurFileName[MAX_PATH]:byte LOCAL hFind:HANDLE ; получаем фильтр для поиска push Directory lea ebx, SearchFilter push ebx call lstrcpy lea ebx, SearchMask push ebx lea ebx, SearchFilter push ebx call lstrcat ; начинаем поиск lea ebx, FindData push ebx lea ebx, SearchFilter push ebx call FindFirstFile mov [hFind], eax inc eax test eax, eax jz scan__finish scan__find_next_file: ; что-то нашли mov eax, [FindData.dwFileAttributes] and eax, FILE_ATTRIBUTE_DIRECTORY test eax, eax jnz scan__its_directory jmp scan__its_file scan__its_directory: ; если нашли папку ; проверяем, что это не . или .. lea esi, FindData.cFileName lodsb cmp al, '.' jne scan__its_real_dir lodsb test al, al je scan__continue cmp al, '.' jne scan__its_real_dir lodsb test al, al je scan__continue scan__its_real_dir: ; рекурсивно заходим в найденную папку push [Directory] lea ebx, CurFileName push ebx call lstrcpy lea ebx, Slash push ebx lea ebx, CurFileName push ebx call lstrcat lea ebx, [FindData.cFileName] push ebx lea ebx, CurFileName push ebx call lstrcat lea ebx, CurFileName push ebx call scan_directory jmp scan__continue scan__its_file: ; если нашли файл ; что-нибудь с ним делаем scan__continue: ; переходим к следующему файлу lea ebx, FindData push ebx push [hFind] call FindNextFile test eax, eax jnz scan__find_next_file ; конец push [hFind] call FindClose scan__finish: ret scan_directory ENDP start: lea ebx, ThisDirectory push ebx call scan_directory ... end start
Пытаюсь переделать свою функцию в рекурсивную Код (Text): updirmask db "..",0 slash db "\",0 pathanymask db "\*",0 FindandDelete proc LOCAL WFD:WIN32_FIND_DATA invoke lstrcpy,addr curentdirectory,ADDR fullpathfordelete invoke SetCurrentDirectory,ADDR fullpathfordelete invoke lstrcat,addr fullpathfordelete,addr pathanymask invoke FindFirstFile,addr fullpathfordelete,addr WFD cmp eax,INVALID_HANDLE_VALUE je exit1 mov hFind,eax deleting: invoke FindNextFile,hFind,addr WFD test eax,eax jz exit1 cmp WFD.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY jne @F invoke lstrcmp,addr WFD.cFileName,addr updirmask cmp eax,0 je @F invoke lstrcpy,addr curentdirectory1,ADDR curentdirectory invoke lstrcat,addr curentdirectory1,addr slash invoke lstrcat,addr curentdirectory1,addr WFD.cFileName invoke lstrcpy,addr fullpathfordelete,ADDR curentdirectory1 invoke FindandDelete @@: invoke DeleteFile,addr WFD.cFileName jmp deleting exit1: invoke FindClose,hFind ret FindandDelete endp Прога вылетает. Где ошибка? Как сделать правильно?
0) атрибуты объекта - это маска, поэтому проверять надо через AND/TEST. 1) кроме ".." есть ещё и "." 2) использовать глобальные переменные в рекурсии не кузяво. 3) поищи по форуму, уж чего-чего, а примеров рекурсивного поиска и удаления файлов валом.
Так тоже работает. Согласен. Поэтому invoke FindFirstFile,firstdirectory,addr WFD cmp eax,INVALID_HANDLE_VALUE je exit1 mov hFind,eax deleting: invoke FindNextFile,hFind,addr WFD Больше не буду. Раньше искал. Ничего подходящего не нашёл. Учёл все советы. Код (Text): FindandDelete proc firstdirectory:DWORD LOCAL curentdirectory[MAX_PATH] :byte LOCAL curentdirectory1[MAX_PATH] :byte LOCAL WFD :WIN32_FIND_DATA invoke lstrcpy,addr curentdirectory,firstdirectory invoke SetCurrentDirectory,firstdirectory invoke lstrcat,firstdirectory,addr pathanymask invoke FindFirstFile,firstdirectory,addr WFD cmp eax,INVALID_HANDLE_VALUE je exit1 mov hFind,eax deleting: invoke FindNextFile,hFind,addr WFD test eax,eax jz exit1 cmp WFD.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY jne @F invoke lstrcmp,addr WFD.cFileName,addr updirmask cmp eax,0 je @F invoke lstrcpy,addr curentdirectory1,ADDR curentdirectory invoke lstrcat,addr curentdirectory1,addr slash invoke lstrcat,addr curentdirectory1,addr WFD.cFileName invoke lstrcpy,addr fullpathfordelete,ADDR curentdirectory1 invoke FindandDelete,ADDR fullpathfordelete @@: invoke DeleteFile,addr WFD.cFileName jmp deleting exit1: invoke FindClose,hFind ret FindandDelete endp Кажется, теперь похоже на правду, но прога всё равно вылетает. Может кто-нибудь видит ошибку?
Переделал по примеру maxdiver Код (Text): updirmask db "..",0 slash db "\",0 pathanymask db "\*",0 FindandDelete proc Directory :DWORD LOCAL SearchFilter[MAX_PATH] :byte LOCAL CurFileName[MAX_PATH] :byte LOCAL WFD :WIN32_FIND_DATA invoke SetCurrentDirectory,Directory invoke lstrcpy,addr SearchFilter,Directory invoke lstrcat,addr SearchFilter,addr pathanymask invoke FindFirstFile,addr SearchFilter,addr WFD cmp eax,INVALID_HANDLE_VALUE je exit1 mov hFind,eax deleting: invoke FindNextFile,hFind,addr WFD test eax,eax jz exit1 cmp WFD.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY jne @F invoke lstrcmp,addr WFD.cFileName,addr updirmask cmp eax,0 je deleting invoke lstrcpy,addr CurFileName,Directory invoke lstrcat,addr CurFileName,addr slash invoke lstrcat,addr CurFileName,addr WFD.cFileName invoke FindandDelete,addr CurFileName jmp deleting @@: invoke DeleteFile,addr WFD.cFileName jmp deleting exit1: invoke FindClose,hFindret FindandDelete endp Всё равно не работает. Может теперь кто-нибудь увидит ошибку?
Вот оптимизированный вариант функции с исправленной ошибкой. Ошибка была в том что hFind - была глобальной переменной со всеми отсюда последствиями. Код (Text): FindandDelete proc Directory :DWORD LOCAL SearchFilter[MAX_PATH] :BYTE LOCAL CurFileName[MAX_PATH] :BYTE LOCAL WFD :WIN32_FIND_DATA LOCAL hFind :DWORD invoke SetCurrentDirectory,Directory invoke lstrcpy,addr SearchFilter,Directory invoke lstrcat,addr SearchFilter,addr pathanymask invoke FindFirstFile,addr SearchFilter,addr WFD inc eax je exit2 dec eax mov hFind,eax deleting: invoke FindNextFile,hFind,addr WFD xchg eax,ecx jecxz exit1 cmp WFD.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY jne @F invoke lstrcmp,addr WFD.cFileName,addr updirmask xchg eax,ecx jecxz deleting invoke lstrcpy,addr CurFileName,Directory invoke lstrcat,addr CurFileName,addr slash invoke lstrcat,addr CurFileName,addr WFD.cFileName invoke FindandDelete,addr CurFileName jmp deleting @@: invoke DeleteFile,addr WFD.cFileName jmp deleting exit1: invoke FindClose,hFind exit2: ret FindandDelete endp
Второй раз говорю, не будет оно работать толком. Каталоги могут иметь кучу атрибутов помимо атрибута "каталог". Кстати, странно, что при задании маски "*.*" находятся и директории - ведь их имена не содержат точку. Разве что "file." == "file".
так и есть. кстати, по-моему "file." - способ явно указать что у файла пустое расширение (а не расширение по умолчанию) - это имеет смысл в диалогах открытия/сохранения файлов, где имеется расширение по умолчанию. а также в каких-то случаях система автоматически добавляет к "file" без точки расширение "ехе" - но точно не помню когда.