Программно удалить элемент из корзины Windows без диалогового окна пользовательского интерфейса

#c #windows #winapi #recycle-bin

#c #Windows #winapi #корзина

Вопрос:

Я использую IContextMenu with "delete" verb для удаления элементов из корзины, но он вызывает диалоговое окно пользовательского интерфейса, даже если я использую CMIC_MASK_FLAG_NO_UI флаг. Есть ли другой способ удалить файлы из корзины без отображения диалогового окна?

 IContextMenu* contextMenu;
recycleBin->GetUIObjectOf(0, 1, (LPCITEMIDLIST*)(amp;pidl), IID_IContextMenu, 0, (LPVOID *)amp;contextMenu);
CMINVOKECOMMANDINFO ci;
memset(amp;ci, 0, sizeof(ci));
ci.fMask = CMIC_MASK_FLAG_NO_UI;
ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
ci.lpVerb = "delete";
contextMenu->InvokeCommand(amp;ci);
contextMenu->Release();
  

Полный код, включая инициализацию объекта корзины и перечисление элементов, находится в gist

Комментарии:

1. IFileOperation

2. Согласно командам вызова элементов в корзине : » Одним из недостатков корзины является то, что, по крайней мере, до Windows 7, он игнорирует флаг CMIC_MASK_FLAG_NO_UI. Он всегда отображает диалоговое окно подтверждения , если должно произойти что-то опасное (например, перезапись существующего файла). » Поэтому вам, вероятно, придется вручную обнаруживать и отклонять всплывающее подтверждение.

3. @Jonathanpotter’ IFileOperation s DeleteItem справился с задачей, спасибо.

Ответ №1:

Вы можете установить перехват WH_CBT и в его обратном вызове следить за nCode of HCBT_CREATEWND . Если вы получите совпадающее имя класса (‘# 32770 (Dialog)’?) и соответствующий заголовок либо возвращает ненулевое значение из обратного вызова, вы можете отправить BM_CLICK на Yes кнопку click, и диалоговое окно будет автоматически закрыто.

Пример кода:

main.cpp

 #include <iostream>
#include <windows.h>
#include <Ole2.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <string>

#pragma comment(lib,"Shlwapi.lib")

HHOOK g_hhook;

int main()
{
    OleInitialize(0);

    HINSTANCE hinstDLL = LoadLibrary(TEXT("D:\xxx\Dll_WH_CBT\Debug\Dll_WH_CBT.dll"));
    HHOOK(*AttachHookProc)(DWORD);
    AttachHookProc = (HHOOK(*)(DWORD)) GetProcAddress(hinstDLL, "AttachHook");
    void(*RemoveHooks)(DWORD);
    RemoveHooks = (void(*)(DWORD))GetProcAddress(hinstDLL, "RemoveHooks");

    IShellFolder* desktop;
    if (FAILED(SHGetDesktopFolder(amp;desktop))) {
        std::cerr << "Failed to get desktop fodler" << std::endl;
        return -1;
    }

    ...
    IEnumIDList* enumFiles;
    if (FAILED(recycleBin->EnumObjects(0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | 
SHCONTF_INCLUDEHIDDEN, amp;enumFiles)))
    {
        std::cerr << "Could not enumerate recycle bin objects" << std::endl;
        recycleBin->Release();
        return -1;
    }

    AttachHookProc(0);

    ...
      
    RemoveHooks(0);
    enumFiles->Release();
    recycleBin->Release();

    OleUninitialize();
    return 0;
}
  

Dll:

 // dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <Windows.h>

HMODULE thisModule;
HHOOK g_hhook;

LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{        
    switch (nCode)
    {
    case HCBT_CREATEWND:
    {      
        HWND File_Window = FindWindow(L"#32770", L"Delete File"); 
        HWND Folder_Window = FindWindow(L"#32770", L"Delete Folder");
        if (File_Window)
        {
            HWND yes = FindWindowEx(File_Window, NULL, L"Button", L"amp;Yes");
            SendMessage(yes, BM_CLICK, 0, 0);
            SendMessage(yes, BM_CLICK, 0, 0);
        }
        if (Folder_Window)
        {
            HWND yes = FindWindowEx(Folder_Window, NULL, L"Button", L"amp;Yes");
            SendMessage(yes, BM_CLICK, 0, 0);
            SendMessage(yes, BM_CLICK, 0, 0);
        }
        break;
    }
    default:
        break;
    }
    return CallNextHookEx(g_hhook, nCode, wParam, lParam);
}

#ifdef __cplusplus    //If used by C   code.
extern "C" {        //we need to export the C interface
#endif
    _declspec(dllexport) HHOOK AttachHook(DWORD threadID) {
        g_hhook = SetWindowsHookEx(WH_CBT, CBTProc, thisModule, threadID);

        return g_hhook;
    }
#ifdef __cplusplus
}
#endif

extern "C" {        //we need to export the C interface
    __declspec(dllexport) void RemoveHooks(DWORD)
    {
        UnhookWindowsHookEx(g_hhook);
    }
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    thisModule = hModule;
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:      
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:

        break;
    }
    return TRUE;
}