ACTK实现:SetupDi 获得设备列表
SetupDi 函数(主要介绍输出设备列表使用到的函数)
包含头文件和库
#include <SetupAPI.h>
#pragma comment(lib,"SetupAPI.lib")
【第一】SetupDiGetClassDevs
【函数说明】:获取一个指定类别(如全部的麦克风)或全部类别的所以已安装设备的信息的句柄
【函数原型】:
HDEVINFO SetupDiGetClassDevs(
_In_opt_ const GUID *ClassGuid,
_In_opt_ PCTSTR Enumerator,
_In_opt_ HWND hwndParent,
_In_ DWORD Flags
);
【参数说明】:
- ClassGuid : 一个特定类别GUID的指针(可以通过设备管理查询)
- Enumerator : 过滤枚举的内容:如:PCI则只显示PCI设备,
- hwndParent : 用于关联到集合成员中的用户接口的顶层窗口句柄
- Flags : 建立设备信息表的控制选项,可以是下列值
- NULL,将返回 guid 指定的设备信息句柄
- DIGCF_ALLCLASSES范围最广:对全部的任何设备类或接口类有支持的设备;此参数将忽略 ClassGuid,将返回所有类别的设备信息表
- DIGCF_DEVICEINTERFACE:仅包含支持设备接口类的设备;
- DIGCF_DEFAULT:仅包含支持默认接口类的设备;
- DIGCF_PRESENT:当前连接的设备;
- DIGCF_PROFILE:Hardware Profile中的设备,要看哪些设备在硬件Profile中,应到注册表键HKLM/SYSTEM/CurrentControlSet/Hardware Profiles/Current/System/CurrentControlSet下查看。
【返回值】
如成功,返回包含所有与指定参数匹配的已经安装设备信息句柄
如失败则返回 INVALID_HANDLE_VALUE
【第二】SetupDiEnumDeviceInfo
【函数原型】
BOOL SetupDiEnumDeviceInfo(
_In_ HDEVINFO DeviceInfoSet,
_In_ DWORD MemberIndex,
_Out_ PSP_DEVINFO_DATA DeviceInfoData
);
【函数说明】
根据SetupDiGetClassDevs返回的设备信息句柄,枚举指定设备信息集合的成员,并将数据放在 PSP_DEVINFO_DATA 中。
【参数说明】
- DeviceInfoSet : 提供一个设备信息集合的句柄
- MemberIndex : 指定一个要取得的设备信息成员序号,从0开始(如第几个麦克风)
- DeviceInfoData : 指向SP_DEVINFO_DATA 结构的指针,关于指定成员的返回信息就放在该结构中
typedef struct _SP_DEVINFO_DATA {
DWORD cbSize; //cbSize设置成sizeof(PSP_DEVINFO_DATA )。
GUID ClassGuid;
DWORD DevInst;
ULONG_PTR Reserved;
} SP_DEVINFO_DATA, *PSP_DEVINFO_DATA;
【返回值】
成功返回True,否则返回False
如果要枚举全部设备信息成员,装载者首先应该将MemberIndex设为0调用SetupDiEnumDeviceInfo,然后递增MemberIndex(使用一个for循环),调用SetupDiEnumDeviceInfo,直至所有成员全部遍历(此时函数返回False,并且GetLastError返回ERROR_NO_MORE_ITEMS)。
【第三】SetupDiGetDeviceRegistryPropertyA
【函数原型】
BOOL SetupDiGetDeviceRegistryPropertyA(
_In_ HDEVINFO DeviceInfoSet,
_In_ PSP_DEVINFO_DATA DeviceInfoData,
_In_ DWORD Property,
_Out_opt_ PDWORD PropertyRegDataType,
_Out_opt_ PBYTE PropertyBuffer,
_In_ DWORD PropertyBufferSize,
_Out_opt_ PDWORD RequiredSize
);
【函数说明】
根据设备信息句柄和设备信息,查找指定设备信息,如设备地址、设备bus号、设备友好名称等
【参数说明】
-
DeviceInfoSet : 设备信息句柄。
-
DeviceInfoData : SP_DEVINFO_DATA结构体,包含DeviceInfoSet中的设备信息
-
Property取以下的值:
- DeviceDesc:设备描述
- SPDRP_HARDWAREID :硬件ID
- SPDRP_MFG:供应商名字
- SPDRP_LOCATION_INFORMATION:本地环境属性(如:PCI 总线 2、设备 10、功能 0)
- SPDRP_FRIENDLYNAME:查询设备名称
- SPDRP_ADDRESS : 查询设备的地址
- SPDRP_BUSNUMBER : 查询设备的bus号
- SPDRP_BUSTYPEGUID : 查询设备的GUID号
-
PropertyRegDataType:指向一个变量的指针,该变量接收正在检索的属性的数据类型。这是标准注册表数据类型之一。此参数是可选的,可以为 NULL。
-
PropertyBuffer:指向接收正在检索的属性的缓冲区的指针。如果此参数设置为 NULL,并且 PropertyBufferSize 也设置为零,则该函数将返回 RequiredSize 中缓冲区所需的大小
-
PropertyBufferSize:属性缓冲区的大小(以字节为单位)
-
RequiredSize:指向 DWORD 类型的变量的指针,该变量接收保存所请求属性的数据所需的属性缓冲区的大小(以字节为单位)。此参数是可选的,可以为 NULL
【备注】
这个函数主要原理是:从注册表中读取指定设备的属性。
此函数还有一个增强版为SetupDiGetDevicePropertyW,可以获取设备所有属性。
【第四】SetupDiDestroyDeviceInfoList
【函数原型】
BOOL SetupDiDestroyDeviceInfoList( HDEVINFO DeviceInfoSet );
【函数说明】
销毁一个设备信息集合,并且释放所有关联的内存
【参数说明】
DeviceInfoSet : 要释放的设备信息句柄
【返回值】
成功返回非零,否则返回零
输出设备列表(以摄像头为例)
代码如下:
void show_camera_device() {
//根据设备管理查找到摄像头 guid 即 {ca3e7ab9-b4c3-4ae6-8251-579ef933890f}
//初始化 guid
unsigned long Data1 = 0xca3e7ab9;
unsigned short Data2 = 0xb4c3;
unsigned short Data3 = 0x4ae6;
unsigned char Data4[8] = {
0x82,
0x51,
0x57,
0x9e,
0xf9,
0x33,
0x89,
0x0f,
};
GUID camera_guid;
camera_guid.Data1 = Data1;
camera_guid.Data2 = Data2;
camera_guid.Data3 = Data3;
for(int i = 0;i < 8;i++)
camera_guid.Data4[i] = Data4[i];
//获得摄像头设备集合句柄 DeviceInfoSet
HDEVINFO DeviceInfoSet = SetupDiGetClassDevsW(&camera_guid, NULL, NULL, NULL);
if (DeviceInfoSet == INVALID_HANDLE_VALUE)
printf("error\n");
//遍历摄像头集合中所有摄像头序列
for (int i = 0; ; i++)
{
//存储第i个摄像头信息
SP_DEVINFO_DATA DeviceInfoData;
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
if (!SetupDiEnumDeviceInfo(DeviceInfoSet, i, &DeviceInfoData))
break;
/*char szDeviceID[256] = {};
DWORD dwTemp = 0;
SetupDiGetDeviceInstanceIdW(DeviceInfoSet, &DeviceInfoData, (PWSTR)szDeviceID, 256, &dwTemp);*/
DEVPROPKEY devicePropertyKey[256] = { 0 };
DWORD RequiredSize = 0;
DEVPROPTYPE PropertyType = 0;
CHAR PropertyBuffer[8192] = { 0 }; //存储需要查询的信息
DWORD DataT = 0;
//获得当前摄像头的名字
SetupDiGetDeviceRegistryPropertyA(DeviceInfoSet, &DeviceInfoData, SPDRP_FRIENDLYNAME,&DataT,reinterpret_cast<PBYTE>(PropertyBuffer), 8192, &RequiredSize);
printf("name:%s\n", PropertyBuffer);
}
//销毁设备信息集合,并且释放相关内存
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}