CM系のAPIを使用してローカルコンピューターのデバイス列挙子とデバイスIDリストを取得するコードです。C++23で導入予定のstd::ranges::to
を使用しています(MSVCのPreview版)。
#include <ranges> #include <algorithm> #include <iostream> #include <string> #include <vector> #define STRICT #define NOMINMAX #include <Windows.h> #include <Cfgmgr32.h> #pragma comment(lib, "cfgmgr32.lib") // ローカルコンピューターのデバイス列挙子をすべて取得します。 std::vector<std::wstring> GetConfigManagerEnumerators() { std::vector<std::wstring> ss; std::wstring s(MAX_DEVICE_ID_LEN, L'\0'); for (ULONG i = 0; i < ULONG_MAX; i++) { ULONG size = MAX_DEVICE_ID_LEN; auto cret = CM_Enumerate_EnumeratorsW(i, s.data(), &size, 0); if (cret == CR_NO_SUCH_VALUE) break; if (cret != CR_SUCCESS) return {}; ss.emplace_back(s.data(), size); } return ss; } // デバイス列挙子からローカルコンピューターのデバイスIDリストを取得します。 std::wstring GetConfigManagerDeviceIDList(std::wstring_view filter, DWORD flags) { ULONG len; if (CM_Get_Device_ID_List_SizeW(&len, filter.data(), flags) != CR_SUCCESS) return {}; std::wstring s(len - 1, L'\0'); if (CM_Get_Device_ID_ListW(filter.data(), s.data(), len, flags) != CR_SUCCESS) return {}; s.resize(s.size() - 1); return s; } // 文字列を特定文字で区切った文字列のベクトルを作成します。 std::vector<std::wstring> SplitStringIntoVector( std::wstring_view sv, wchar_t delimiter) { return std::views::lazy_split(sv, delimiter) | std::views::transform([](auto view) { return std::views::common(view) | std::ranges::to<std::wstring>(); }) | std::ranges::to<std::vector>(); } int main() { const auto enumerators = GetConfigManagerEnumerators(); std::ranges::copy( enumerators, std::ostream_iterator<std::wstring, wchar_t>(std::wcout, L"\n")); const auto& enumerator = enumerators[0]; std::wcout << std::endl << enumerator << std::endl; auto ids_raw = GetConfigManagerDeviceIDList(enumerator, CM_GETIDLIST_FILTER_ENUMERATOR); auto ids = SplitStringIntoVector(ids_raw, L'\0'); std::ranges::copy( ids, std::ostream_iterator<std::wstring, wchar_t>(std::wcout, L"\n")); return 0; }