デバイス情報要素の文字列プロパティ(概要、クラス、クラスGUID、フレンドリーネーム、ハードウェアID)を列挙するコードです。再利用可能なコードをUtility.hpp
へ移動しています。
文字列プロパティ(概要、クラス、クラスGUID、フレンドリーネーム、ハードウェアID)を列挙する
Main.cpp
#pragma comment(lib, "SetupAPI.lib")
#define STRICT
#define NOMINMAX
#include <Windows.h>
#include <SetupAPI.h>
#include "Utility.hpp"
#include <iostream>
#include <format>
int main()
{
std::wcout.imbue(std::locale("", std::locale::ctype));
auto DevInfoHandle{ unique_SetupDiGetClassDevsW(
nullptr,
nullptr,
nullptr,
DIGCF_ALLCLASSES) };
std::wstring DevDesc;
std::wstring DevClass;
std::wstring DevClassGuid;
std::wstring DevFriendlyName;
std::wstring DevHardwareId;
std::wcout << L"ClassGuid, DevInst, SPDRP_DEVICEDESC, SPDRP_CLASS, SPDRP_CLASSGUID, SPDRP_FRIENDLYNAME, SPDRP_HARDWAREID" << std::endl;
for (auto& DevInfoData : SetupDiCreateDeviceInfoDataList(DevInfoHandle.get()))
{
SetupDiGetDeviceRegistryPropertyAsStringW(DevDesc,
DevInfoHandle.get(), &DevInfoData, SPDRP_DEVICEDESC);
SetupDiGetDeviceRegistryPropertyAsStringW(DevClass,
DevInfoHandle.get(), &DevInfoData, SPDRP_CLASS);
SetupDiGetDeviceRegistryPropertyAsStringW(DevClassGuid,
DevInfoHandle.get(), &DevInfoData, SPDRP_CLASSGUID);
SetupDiGetDeviceRegistryPropertyAsStringW(DevFriendlyName,
DevInfoHandle.get(), &DevInfoData, SPDRP_FRIENDLYNAME);
SetupDiGetDeviceRegistryPropertyAsStringW(DevHardwareId,
DevInfoHandle.get(), &DevInfoData, SPDRP_HARDWAREID);
std::wcout
<< std::format(L"{}, {}, {}, {}, {}, {}, {}",
GUIDToWString(DevInfoData.ClassGuid),
DevInfoData.DevInst,
DevDesc.c_str(),
DevClass.c_str(),
DevClassGuid.c_str(),
DevFriendlyName.c_str(),
DevHardwareId.c_str())
<< std::endl;
}
}
Utility.hpp
#pragma once
#include <bit>
#include <memory>
#include <string>
#include <numeric>
#include <list>
std::wstring GUIDToWString(const GUID& guid)
{
std::wstring s(38, L'\0');
if (FAILED(::StringFromGUID2(guid, s.data(), 38)))
return {};
return std::move(s);
}
struct HDEVINFO_deleter {
void operator() (HDEVINFO handle) const noexcept {
::SetupDiDestroyDeviceInfoList(handle);
}
};
using unique_HDEVINFO = std::unique_ptr<std::remove_pointer_t<HDEVINFO>, HDEVINFO_deleter>;
unique_HDEVINFO unique_SetupDiGetClassDevsW(
const GUID* ClassGuid,
LPCWSTR Enumerator,
HWND hWndParent,
DWORD Flags) noexcept
{
return unique_HDEVINFO(::SetupDiGetClassDevsW(ClassGuid, Enumerator, hWndParent, Flags));
}
std::list<SP_DEVINFO_DATA> SetupDiCreateDeviceInfoDataList(HDEVINFO DeviceInfoSet)
{
std::list<SP_DEVINFO_DATA> DevInfoDatas;
for (DWORD i = 0; i < std::numeric_limits<DWORD>::max(); i++)
{
SP_DEVINFO_DATA DevInfoData{ sizeof(SP_DEVINFO_DATA) };
if (!SetupDiEnumDeviceInfo(DeviceInfoSet, i, &DevInfoData))
break;
DevInfoDatas.emplace_back(DevInfoData);
}
return std::move(DevInfoDatas);
}
BOOL SetupDiGetDeviceRegistryPropertyAsStringW(
std::wstring& result,
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property)
{
DWORD RequiredSize;
DWORD PropertyRegDataType;
if (!::SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData,
Property, &PropertyRegDataType, nullptr, 0, &RequiredSize)
&& ::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
return FALSE;
}
if (PropertyRegDataType != REG_SZ)
{
::SetLastError(ERROR_INVALID_DATATYPE);
return FALSE;
}
result.resize(RequiredSize);
return ::SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData,
Property, nullptr, std::bit_cast<PBYTE>(result.data()), result.size(), nullptr);
}
クラスを列挙する
#pragma once
#include <bit>
#include <memory>
#include <string>
#include <numeric>
#include <list>
std::wstring GUIDToWString(const GUID& guid)
{
std::wstring s(38, L'\0');
if (FAILED(::StringFromGUID2(guid, s.data(), 38)))
return {};
return std::move(s);
}
struct HDEVINFO_deleter {
void operator() (HDEVINFO handle) const noexcept {
::SetupDiDestroyDeviceInfoList(handle);
}
};
using unique_HDEVINFO = std::unique_ptr<std::remove_pointer_t<HDEVINFO>, HDEVINFO_deleter>;
unique_HDEVINFO unique_SetupDiGetClassDevsW(
const GUID* ClassGuid,
LPCWSTR Enumerator,
HWND hWndParent,
DWORD Flags) noexcept
{
return unique_HDEVINFO(::SetupDiGetClassDevsW(ClassGuid, Enumerator, hWndParent, Flags));
}
std::list<SP_DEVINFO_DATA> SetupDiCreateDeviceInfoDataList(HDEVINFO DeviceInfoSet)
{
std::list<SP_DEVINFO_DATA> DevInfoDatas;
for (DWORD i = 0; i < std::numeric_limits<DWORD>::max(); i++)
{
SP_DEVINFO_DATA DevInfoData{ sizeof(SP_DEVINFO_DATA) };
if (!SetupDiEnumDeviceInfo(DeviceInfoSet, i, &DevInfoData))
break;
DevInfoDatas.emplace_back(DevInfoData);
}
return std::move(DevInfoDatas);
}
BOOL SetupDiGetDeviceRegistryPropertyAsStringW(
std::wstring& result,
HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
DWORD Property)
{
DWORD RequiredSize;
DWORD PropertyRegDataType;
if (!::SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData,
Property, &PropertyRegDataType, nullptr, 0, &RequiredSize)
&& ::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
return FALSE;
}
if (PropertyRegDataType != REG_SZ)
{
::SetLastError(ERROR_INVALID_DATATYPE);
return FALSE;
}
result.resize(RequiredSize);
return ::SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData,
Property, nullptr, std::bit_cast<PBYTE>(result.data()),
static_cast<DWORD>(result.size()), nullptr);
}
クラスに対応するデバイス情報要素の概要を列挙する
#pragma comment(lib, "SetupAPI.lib")
#define STRICT
#define NOMINMAX
#include <Windows.h>
#include <SetupAPI.h>
#include "Utility.hpp"
#include <iostream>
#include <set>
int main()
{
std::wcout.imbue(std::locale("", std::locale::ctype));
auto DevInfoHandle{ unique_SetupDiGetClassDevsW(
nullptr,
nullptr,
nullptr,
DIGCF_ALLCLASSES) };
std::set<std::wstring> DevClassSet;
std::wstring Buffer;
for (auto& DevInfoData : SetupDiCreateDeviceInfoDataList(DevInfoHandle.get()))
{
SetupDiGetDeviceRegistryPropertyAsStringW(Buffer,
DevInfoHandle.get(), &DevInfoData, SPDRP_CLASS);
DevClassSet.emplace(Buffer.c_str());
}
for (const auto& DevClass : DevClassSet)
{
wcout << DevClass << endl;
}
}