Blog. Just Blog

Программное удаление файла в Корзину

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Небольшой сниппет - удаление файла или группы файлов в Корзину. Делается это при помощи функции SHFileOperation, но сперва нам надо будет определить необходимую структуру SHFILEOPSTRUCT и несколько констант.
  1. struct SHFILEOPSTRUCT
  2.         hwnd                  dd ?
  3.         wFunc                 dd ?
  4.         pFrom                 dd ?
  5.         pTo                   dd ?
  6.         fFlags                dw ?
  7.         fAnyOperationsAborted dd ?
  8.         hNameMappings         dd ?
  9.         lpszProgressTitle     dd ?
  10. ends
  11.  
  12. FO_DELETE = 3h
  13.  
  14. FOF_ALLOWUNDO      = 40h
  15. FOF_NOCONFIRMATION = 10h
  16. FOF_SILENT         = 4h
Сам код очень простой. Указываем тип операции FO_DELETE, то есть удаление, в параметре pFrom передаем список объектов на удаление, флагами настраиваем поведение - удалять с возможностью отката (то есть в Корзину), не показывать никаких подтверждений и диалогов.
  1.         mov     [fos.hwnd],HWND_DESKTOP
  2.         mov     [fos.wFunc],FO_DELETE
  3.         mov     [fos.pFrom],fname
  4.         mov     [fos.fFlags],FOF_ALLOWUNDO+FOF_NOCONFIRMATION+FOF_SILENT
  5.         invoke  SHFileOperation,fos
Обратите внимание, что список объектов должен заканчиваться двойным нулевым символом, даже если удаляется один файл. Также при удалении файлов со съемных носителей они могут удаляться без попадания в Корзину, но это как и при удалении через Проводник Windows.

Начиная с Windows Vista, файловые операции через функцию SHFileOperation считаются устаревшими, и Microsoft рекомендует использовать вместо них операции через COM-объекты. Неизбежно это тянет за собой тонну писанины: идентификаторы, интерфейсы, константы, достаточно объемный код реализации.
  1. ; GUID {3AD05575-8857-4850-9277-11B85BDB8E09}
  2. CLSID_FileOperation dd 03AD05575h
  3.                     dw 08857h
  4.                     dw 04850h
  5.                     db 092h, 077h, 011h, 0B8h, 05Bh, 0DBh, 08Eh, 009h
  6.  
  7. ; GUID {947AAB5F-0A5C-4C13-B4D6-4BF7836FC9F8}
  8. IID_IFileOperation  dd 0947AAB5Fh
  9.                     dw 00A5Ch
  10.                     dw 04C13h
  11.                     db 0B4h, 0D6h, 04Bh, 0F7h, 083h, 06Fh, 0C9h, 0F8h
  12.  
  13. ; GUID {43826D1E-E718-42EE-BC55-A1E261C37BFE}
  14. IID_IShellItem      dd 043826D1Eh
  15.                     dw 0E718h
  16.                     dw 042EEh
  17.                     db 0BCh, 055h, 0A1h, 0E2h, 061h, 0C3h, 07Bh, 0FEh
  18.  
  19. ; IID_IFileOperation Interface
  20. struct IFileOperationDispatch
  21.     QueryInterface          dd ?
  22.     AddRef                  dd ?
  23.     Release                 dd ?
  24.  
  25.     ; IFileOperation
  26.     Advise                  dd ?
  27.     Unadvise                dd ?
  28.     SetOperationFlags       dd ?
  29.     SetProgressMessage      dd ?
  30.     SetProgressDialog       dd ?
  31.     SetProperties           dd ?
  32.     SetOwnerWindow          dd ?
  33.     ApplyPropertiesToItem   dd ?
  34.     ApplyPropertiesToItems  dd ?
  35.     RenameItem              dd ?
  36.     RenameItems             dd ?
  37.     MoveItem                dd ?
  38.     MoveItems               dd ?
  39.     CopyItem                dd ?
  40.     CopyItems               dd ?
  41.     DeleteItem              dd ?
  42.     DeleteItems             dd ?
  43.     NewItem                 dd ?
  44.     PerformOperations       dd ?
  45.     GetAnyOperationsAborted dd ?
  46. ends
  47.  
  48. CLSCTX_INPROC_SERVER    = 1
  49. S_OK                    = 0
Сам код удаления будет включать несколько шагов, помимо стандартных операций с COM-объектами. Сперва устанавливаются флаги операции, к счастью, они совпадают с флагами SHFileOperation. Затем из имени файла надо создать COM-объект типа IShellItem, потому что методы объекта IFileOperation умеют работать только с такими сущностями. После этого выбирается тип выполняемой операции - удаление файла. И только выполнив все эти приготовления, можно будет выполнить саму операцию. На мой взгляд, замена одной функции подобной свистопляской - такое себе "удобство".
  1.         ; Инициализировать COM-объект
  2.         invoke  CoInitialize,NULL
  3.         ; Создать объект
  4.         invoke  CoCreateInstance,CLSID_FileOperation,NULL,\
  5.                 CLSCTX_INPROC_SERVER,\
  6.                 IID_IFileOperation,pIFoDisp
  7.         cmp     eax,S_OK
  8.         jne     loc_exit
  9.  
  10.         ; Установить флаги выполняемой операции
  11.         mov     eax, [pIFoDisp]
  12.         mov     eax, [eax]
  13.         stdcall dword [eax+IFileOperationDispatch.SetOperationFlags],\
  14.                 [pIFoDisp],FOF_ALLOWUNDO+FOF_NOCONFIRMATION+FOF_SILENT
  15.  
  16.         ; Создать объект IShellItem из пути к файлу
  17.         invoke  SHCreateItemFromParsingName,filename,NULL,IID_IShellItem,\
  18.                 deleteItem
  19.  
  20.         ; Подготовить операцию удаления файла
  21.         mov     eax, [pIFoDisp]
  22.         mov     eax, [eax]
  23.         stdcall dword [eax+IFileOperationDispatch.DeleteItem],\
  24.                 [pIFoDisp],[deleteItem],NULL
  25.  
  26.         ; Выполнить операцию
  27.         mov     eax, [pIFoDisp]
  28.         mov     eax, [eax]
  29.         stdcall dword [eax+IFileOperationDispatch.PerformOperations],[pIFoDisp]
  30.  
  31.         ; Прибраться за собой
  32.         mov     eax, [pIFoDisp]
  33.         mov     eax, [eax]
  34.         stdcall dword [eax+IFileOperationDispatch.Release],[pIFoDisp]
  35.  
  36.         ; Удалить объект
  37.         invoke  CoUninitialize
Из дополнительных особенностей стоит отметить, что методы IFileOperation работают исключительно с юникодными строками, а путь к файлу при преобразовании в объект должен быть полным, то есть включать в себя и название каталога. Столько лишних движений ради простейшей операции.

Если возможность восстановления не важна, то в остальных случаях для удаления файлов лучше все-таки использовать функцию DeleteFile.

В приложении примеры программ с исходными текстами, которые создают временный файл "test.txt", а затем удаляют его в Корзину разными способами.

Примеры программ с исходными текстами (FASM)Примеры программ с исходными текстами (FASM)

Delete.to.Recycle.Bin.Demo.zip (3,757 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 1208 | Комментариев: 6

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (14.05.2024 в 15:16):
Так для каждого удаляемого файла надо заполнять элемент массива pidl, он же не автоматически всей пачкой заполняется. Тут https://forum.sources.ru/index...topic=366720 не совсем в тему, но принцип тот же.
assch (14.05.2024 в 14:35):
у метода (ParseDisplayName) интерфейса - IShellFolder
прописываю (6) параметров --> NULL,0,адрес символов первого файла,0,addr pidl,NULL
всё равно возвращает только один идентификатор в - pidl
assch (14.05.2024 в 12:25):
Большое спасибо,попробую разобраться
ManHunter (14.05.2024 в 10:57):
https://learn.microsoft.com/en...-deleteitems
Единственным параметром передается список объектов в формате IShellItemArray, IDataObject или IEnumShellItems. И на каждый из этих списков добавится еще по три экрана кода, чтобы его создать.

Вкратце: создается массив ITEMIDLIST https://firststeps.ru/cbuilder/r.php?80=  , дальше через SHCreateShellItemArrayFromIDLists создается объект IShellItemArray, затем он передается в DeleteItems.

"попробывать", "Не подскажите" - за что так с русским языком? :(
и еще вот  [,,,,,,,,,......] коробочка со знаками препинания, а то потерялись где-то по дороге. Читать невозможно.
assch (14.05.2024 в 09:42):
Хороший метод только жалко что он сможет удалить только один файд
например если перетащить в окно группу файлов то сообщение - WM_DROPFILES
вернёт в параметре (wParam) дескриптор внутренней структуры
в этой структуре первым параметром прописано смещение
на символьные пути файла или файлов в формате - UNICODE
например если удалять без интерфейса

mov eax,wParam
mov eax,dword ptr [eax]
add eax,dword ptr [eax]
mov sfs.pFrom,eax                ; адрес символов файлов в формате - UNICODE
invoke SHFileOperationW,addr sfs ; соответственно только функция - UNICODE
invoke DragFinish,wParam         ; освободим память выделенную системой

Работает на ура выше всяких похвал
но ради интереса хочется попробывать интерфейсом
и вот если скормить этот адрес путей файлов
функции - SHCreateItemFromParsingName
то благополучно переместится в корзину только один файл видимо первый в списке
а вот как сделать чтобы все файлы ушли в корзину
в интерфейсе - IFileOperation
помимо метода - DeleteItem
есть ещё и метод - DeleteItems
но вот как его реализовать не пойму
кручу верчу ничего не получается

Не подскажите
ManHunter (26.08.2020 в 16:37):
Добавил реализацию удаления через COM-объекты. Архив обновлен.

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.08 сек. / MySQL: 2 (0.008 сек.) / Память: 4.5 Mb
Наверх