potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。はてなブログ無料版なので記事の上の方はたぶん広告です。記事中にも広告挿入されるみたいです。

C++20&WIL ごみ箱内の項目の「元の場所」「削除された日時」を取得する

C++20とWILでごみ箱内の項目の「元の場所」と「削除された日時」を取得するサンプルコードです。実行すると表示名とそれらを出力します。

#include <format>
#include <functional>
#include <iostream>

#define STRICT
#define NOMINMAX
#include <Windows.h>
#include <ShlObj.h>
#pragma comment(lib, "propsys.lib")

// Microsoft WIL 1.0.220201.1
#include "wil/com.h"

void ForEachItems(IShellItem* pparent, std::function<void(IShellItem*)> fn)
{
    wil::com_ptr<IEnumShellItems> pitems;
    THROW_IF_FAILED(pparent->BindToHandler(
        nullptr, BHID_EnumItems, IID_PPV_ARGS(pitems.put())));

    wil::com_ptr<IShellItem> pitem;
    HRESULT hr;
    while ((hr = items->Next(1, item.put(), nullptr)) != S_FALSE)
    {
        THROW_IF_FAILED(hr);
        fn(item.get());
    }
}

inline PROPERTYKEY PSGetPropertyKeyFromName(PCWSTR propName)
{
    PROPERTYKEY pkey;
    THROW_IF_FAILED(PSGetPropertyKeyFromName(propName, &pkey));
    return pkey;
}

int main()
{
    std::wcout.imbue(std::locale("", std::locale::ctype));

    auto coinit{ wil::CoInitializeEx(COINIT_APARTMENTTHREADED) };

    wil::com_ptr<IShellItem> recycleBin;
    THROW_IF_FAILED(SHGetKnownFolderItem(
        FOLDERID_RecycleBinFolder, KF_FLAG_DEFAULT, nullptr, IID_PPV_ARGS(recycleBin.put())));

    const auto pkeyDateDeleted{ PSGetPropertyKeyFromName(L"System.Recycle.DateDeleted") };
    const auto pkeyDeletedFrom{ PSGetPropertyKeyFromName(L"System.Recycle.DeletedFrom") };

    std::wcout << L"名前, 元の場所, 削除された日時" << std::endl;
    ForEachItems(recycleBin.get(), [&pkeyDateDeleted, &pkeyDeletedFrom](IShellItem* pitem)
        {
            auto pitem2{ wil::com_query<IShellItem2>(pitem) };

            wil::unique_cotaskmem_string displayName;
            pitem->GetDisplayName(SIGDN_NORMALDISPLAY, displayName.put());

            // 元の場所
            wil::unique_cotaskmem_string deletedFrom;
            pitem2->GetString(pkeyDeletedFrom, deletedFrom.put());

            // 削除された日時
            FILETIME ftDateDeleted;
            std::wstring dateDeletedStr;
            if (SUCCEEDED(pitem2->GetFileTime(pkeyDateDeleted, &ftDateDeleted)))
            {
                SYSTEMTIME dateDeleted;
                FileTimeToLocalFileTime(&ftDateDeleted, &ftDateDeleted);
                FileTimeToSystemTime(&ftDateDeleted, &dateDeleted);
                dateDeletedStr = std::format(L"{}/{}/{} {}:{}:{}",
                    dateDeleted.wYear, dateDeleted.wMonth, dateDeleted.wDay,
                    dateDeleted.wHour, dateDeleted.wMinute, dateDeleted.wSecond);
            }
            std::wcout
                << std::format(L"{}, {}, {}",
                    displayName.get(), deletedFrom.get(), dateDeletedStr)
                << std::endl;
        });

    return 0;
}