想写一个类似“设备管理器”这样的程序

找了一些资料,发现就用三个函数可以了:
SetupDiGetClassDevs,SetupDiEnumDeviceInfo,SetupDiGetDeviceRegistryProperty。其实这三个函数跟遍历文件夹非常相似,创建一个句柄,然后利用这个句柄枚举每一项已经安装到系统的设备,然后再读取每一项设备的详细信息值。例如:设备名,驱动程序,所属驱动分类名,系统总线号,等等
1 首先使用SetupDiGetClassDevsA或SetupDiGetClassDevsW函数创建一个设备信息集句柄。
HDEVINFO SetupDiGetClassDevsA(const GUID *ClassGuid,PCWSTR Enumerator,HWND hwndParent,DWORD Flags);
2 然后利用得到的信息设备集句柄,进行枚举 SetupDiEnumDeviceInfo
BOOL SetupDiEnumDeviceInfo(HDEVINFO DeviceInfoSet,DWORD MemberIndex,PSP_DEVINFO_DATA DeviceInfoData);
第一参数就填SetupDiGetClassDevs的返回值句柄;
第二个参数就是要检索的设备信息索引值,从零开始;
第三参数是一个指向SP_DEVINFO_DATA结构的指针,当函数执行成功之后,函数会往该结构填写一些数据
这里重点说下第二个参数,如何知道系统一共有多少个设备呢?其实没人懂啊~~~那怎么办啊,用循环的方法呗,将索引值从零开始累加,直到返回FALSE,就是说明已经没有设备啦。
3 枚举得到设备之后,就可以查询这个设备的各种详细信息啦
BOOL SetupDiGetDeviceRegistryPropertyA(HDEVINFO DeviceInfoSet,PSP_DEVINFO_DATA DeviceInfoData,DWORD Property,PDWORD PropertyRegDataType,PBYTE PropertyBuffer,DWORD PropertyBufferSize,PDWORD RequiredSize);
第一参数就填SetupDiGetClassDevs的返回值句柄;
第二个参数是一个指向SP_DEVINFO_DATA结构的指针,将SetupDiEnumDeviceInfo的第三个参数返回的指针地址填进去
第三个参数是要查询的信息类型,比例说:我们要查询某设备的设备名,驱动程序,系统服务名,系统总线号,等等,常用的值有:SPDRP_CLASS,SPDRP_COMPATIBLEIDS,SPDRP_DEVICEDESC,还有很多值没有列出来,具体可以参考MSDN:https://docs.microsoft.com/zh-cn/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya
第四个参数指向接收正在检索的属性的数据类型的变量的指针。这是标准注册表数据类型之一。此参数是可选的,可以为NULL;
第无个参数就是接收返回值的内存区,当函数执行成功的时候,得到的结果将写入这个内存区
第六个参数是第五个参数内存区的长度
第七个参数内存区里保存的结果的数据长度,当函数执行成功的时候,内存区里面的数据长度。
总体的代码大概是这样的:
hDeviceHand=SetupDiGetClassDevsA(0,0,0,DIGCF_PRESENT | DIGCF_ALLCLASSES);
if (hDeviceInfo != INVALID_HANDLE_VALUE){
MemoryBufMaxLen=1024*1024*1;
char* MemoryBuf=new[MemoryBufMaxLen];
int N=0;
while (true){
SP_DEVINFO_DATA DeviceInfoData;
BOOL cs=SetupDiEnumDeviceInfo(hDeviceInfo,N++,&DeviceInfoData);
if (!cs) break;
DWORD RequiredSize=0;
cs:=SetupDiGetDeviceRegistryProperty(hDeviceInfo,&DeviceInfoData,SPDRP_DEVICEDESC,0,MemoryBuf,MemoryBufMaxLen-1,RequiredSize);
if (cs){
// 函数执行成功,信息就存在MemoryBuf里啦,信息长度为RequiredSize
}
} // end while (true)
} // end if (hDeviceInfo != INVALID_HANDLE_VALUE)
我把运行后的信息保存到文件里了,大概就是这样: