IShellItem
インターフェイスで既知フォルダ(Known Folder)のフォルダID(識別子)と名前を列挙するコードです。実行するとデバッグウィンドウに既知フォルダの数だけ「フォルダID: 名前」を出力します。
#include <format> #include <ranges> #include <vector> #define STRICT #define NOMINMAX #include <Windows.h> #include <ShlObj.h> #include "wil/com.h" // レンジからベクトルを作成します。 template <std::ranges::range Range> inline constexpr std::vector<std::ranges::range_value_t<Range>> to_vector(const Range& r) { return std::vector(std::ranges::cbegin(r), std::ranges::cend(r)); } // KNOWNFOLDER_DEFINITION構造体のWILリソースラッパーです。 using unique_knownfolder_definition = wil::unique_struct< KNOWNFOLDER_DEFINITION, decltype(&FreeKnownFolderDefinitionFields), FreeKnownFolderDefinitionFields>; // wil::com_raw_ptrの型を返します。 template <typename T> using com_raw_ptr_t = decltype(wil::com_raw_ptr(std::declval<T>())); // 型Tの変数にwil::com_raw_ptrを適用した戻り値がInterface*型か判定します。 template<typename T, typename Interface> concept com_raw_ptr_of = std::convertible_to<com_raw_ptr_t<T>, Interface*>; // IKnownFolderManager::GetFolderIdsを呼び出します。 template<com_raw_ptr_of<IKnownFolderManager> T> wil::unique_cotaskmem_array_ptr<GUID> GetFolderIds(T& pmanager) { GUID* pfolderIds; UINT folderIdCount; THROW_IF_FAILED(wil::com_raw_ptr(pmanager)->GetFolderIds(&pfolderIds, &folderIdCount)); return wil::unique_cotaskmem_array_ptr<GUID>(pfolderIds, folderIdCount); } // GUIDをブラケットで挟まれた文字列表現に変換します。 // 失敗時は空の文字列を返します。 inline std::wstring GUIDToWString(const GUID& guid) { const auto size{ std::size(L"{00000000-0000-0000-0000-000000000000}") }; std::wstring s(size - 1, L'\0'); return (StringFromGUID2(guid, s.data(), static_cast<int>(size) + 1) != 0) ? std::move(s) : std::wstring(); } int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) { // COMを初期化する。 auto coinit{ wil::CoInitializeEx(COINIT_APARTMENTTHREADED) }; // KnownFolderManagerのインスタンスを作成する。 auto manager{ wil::CoCreateInstance<KnownFolderManager, IKnownFolderManager>() }; // 特殊フォルダのフォルダIDと名前を列挙する。 wil::unique_cotaskmem_array_ptr<GUID> folderIds{ GetFolderIds(manager) }; auto view{ folderIds | std::ranges::views::transform( [&manager](const auto& folderId) { wil::com_ptr<IKnownFolder> folder; THROW_IF_FAILED(manager->GetFolder(folderId, folder.put())); unique_knownfolder_definition definition; THROW_IF_FAILED(folder->GetFolderDefinition(&definition)); return std::make_tuple(folderId, std::wstring(definition.pszName)); } ) }; // 確認用にデバッガーへ出力します。 // デバッグ用にstd::vectorにします。 auto infos{ to_vector(view) }; for (const auto& info : infos) { auto s{ std::format(L"{}: {}\n", GUIDToWString(std::get<GUID>(info)), std::get<std::wstring>(info)) }; OutputDebugStringW(s.c_str()); } return 0; }