potisanのプログラミングメモ

プログラミング素人です。昔の自分を育ててくれたネット情報に少しでも貢献できるよう、情報を貯めていこうと思っています。Windows環境のC++やC#がメインです。

C++20&WIL プロパティ記述子を列挙する

C++20とWILでプロパティ記述子(IPropertyDescriptor)を列挙するサンプルコードです。実行するとプロパティの正規名と表示名を出力します。

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

#define STRICT
#define NOMINMAX
#include <Windows.h>
#include <propsys.h>

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

std::wstring GUIDToWString(const GUID& guid)
{
    std::wstring s(38, L'\0');
    ::StringFromGUID2(guid, s.data(), 39);
    return std::move(s);
}

void ForEachPropertyDescriptions(
    IPropertySystem* ppropSys,
    PROPDESC_ENUMFILTER enumFilter,
    std::function<void(IPropertyDescription*)> fn)
{
    wil::com_ptr<IPropertyDescriptionList> propDescs;
    THROW_IF_FAILED(ppropSys->EnumeratePropertyDescriptions(
        enumFilter, IID_PPV_ARGS(propDescs.put())));

    UINT count;
    THROW_IF_FAILED(propDescs->GetCount(&count));
    for (UINT i = 0; i < count; i++)
    {
        wil::com_ptr<IPropertyDescription> propDesc;
        THROW_IF_FAILED(propDescs->GetAt(i, IID_PPV_ARGS(propDesc.put())));
        fn(propDesc.get());
    }
}

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

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

    auto propSys{ wil::CoCreateInstance<PropertySystem, IPropertySystem>() };
    ForEachPropertyDescriptions(
        propSys.get(),
        PROPDESC_ENUMFILTER::PDEF_SYSTEM,
        [](IPropertyDescription* ppropDesc)
        {
            // TODO:ここでIPropertyDescriptionを処理します。
            wil::unique_cotaskmem_string pcanonicalName;
            wil::unique_cotaskmem_string pdisplayName;
            PROPERTYKEY propKey{};
            ppropDesc->GetCanonicalName(pcanonicalName.put());
            ppropDesc->GetDisplayName(pdisplayName.put());
            ppropDesc->GetPropertyKey(&propKey);

            std::wcout
                << std::format(L"{}, {}, ({}, {})",
                    wil::string_get_not_null(pcanonicalName),
                    wil::string_get_not_null(pdisplayName),
                    GUIDToWString(propKey.fmtid),
                    propKey.pid)
                << std::endl;
        });

    return 0;
}