背景及问题:

在与硬件打交道时,经常需要知道当前设备连接的硬件信息,以便连接正确的硬件,比如串口通讯查询连接的硬件及端口,一般手工的方式就是去设备管理器查看相应的信息,应用程序如何读取这一部分信息呢,Windows下的SetupAPI系列就可以解决这个问题

示例程序

#include<Windows.h>
#include<SetupAPI.h>
#include<iostream>
#include<string>
#pragma comment(lib, "setupapi.lib") int main()
{
//set chinese character
std::locale::global(std::locale("")); //The SetupDiGetClassDevs function returns a handle to a device
//information set that contains requested device information
//elements for a local computer.
HDEVINFO hdevinfo = SetupDiGetClassDevs(NULL,
NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
if (hdevinfo != INVALID_HANDLE_VALUE)
{
DWORD MemberIndex = 0;
SP_DEVINFO_DATA sp_devinfo_data;
ZeroMemory(&sp_devinfo_data, sizeof(sp_devinfo_data));
sp_devinfo_data.cbSize = sizeof(sp_devinfo_data); //The SetupDiEnumDeviceInfo function returns a SP_DEVINFO_DATA
//structure that specifies a device information element in a
//device information set.
while (SetupDiEnumDeviceInfo(hdevinfo, MemberIndex, &sp_devinfo_data))
{
TCHAR PropertyBuffer[100]; //The SetupDiGetDeviceRegistryProperty function retrieves
//a specified Plug and Play device property.
if (SetupDiGetDeviceRegistryProperty(hdevinfo,
&sp_devinfo_data,
SPDRP_DEVICEDESC,
NULL,
(PBYTE)&PropertyBuffer,
sizeof(PropertyBuffer),
NULL))
{ std::wcout << MemberIndex << ":" << (wchar_t*)PropertyBuffer << std::endl; }
MemberIndex++; } }
return 0;
}

解释

主要是3个API的使用

  1. SetupDiGetClassDevs -->获取设备信息的集合
  2. SetupDiEnumDeviceInfo -->针对具体的设备解析信息
  3. SetupDiGetDeviceRegistryProperty -->提取具体设备的感兴趣信息

其中SetupDiGetClassDevs定义如下

WINSETUPAPI HDEVINFO SetupDiGetClassDevsW(
[in, optional] const GUID *ClassGuid,
[in, optional] PCWSTR Enumerator,
[in, optional] HWND hwndParent,
[in] DWORD Flags
);
Parameter Description
[in, optional]const GUID *ClassGuid 指向设备设置类或设备接口GUID的指针。可为NULL(可选)
[in, optional] PCWSTR Enumerator 指定设备种类。可为NULL(可选)
[in, optional] HWND hwndParent 显示设备信息UI界面窗口句柄。可为NULL(可选)
[in, optional] DWORD Flags 过滤设备信息标志位
返回值HDEVINFO 返回设备信息的集合

程序中前三个均设置为NULL,第四个标志位设为DIGCF_PRESENT|DIGCF_ALLCLASSES,表示当前系统已安装的所有设备,还有一些标志参见

MSDN页面-SetupDiGetClassDevsW

拿到设备信息集合之后,使用SetupDiEnumDeviceInfo进行单个设备信息的解析

WINSETUPAPI BOOL SetupDiEnumDeviceInfo(
[in] HDEVINFO DeviceInfoSet,
[in] DWORD MemberIndex,
[out] PSP_DEVINFO_DATA DeviceInfoData
);
Parameter Description
[in] HDEVINFO DeviceInfoSet 设备信息集合句柄
[in] DWORD MemberIndex 集合中第几个设备
[out] PSP_DEVINFO_DATA DeviceInfoData 具体的设备信息数据

拿到单个设备的信息之后(仍包含很多信息),使用SetupDiGetDeviceRegistryProperty对感兴趣的信息解析

WINSETUPAPI BOOL SetupDiGetDeviceRegistryPropertyW(
[in] HDEVINFO DeviceInfoSet,
[in] PSP_DEVINFO_DATA DeviceInfoData,
[in] DWORD Property,
[out, optional] PDWORD PropertyRegDataType,
[out, optional] PBYTE PropertyBuffer,
[in] DWORD PropertyBufferSize,
[out, optional] PDWORD RequiredSize
);
Parameter Description
[in] HDEVINFO 设备信息集合句柄
[in] PSP_DEVINFO_DATA DeviceInfoData 具体的设备信息数据
[in] DWORD Property 设备属性
[out, optional] PDWORD PropertyRegDataType 指向接收所检索属性的数据类型变量的指针。可为NULL(可选)
[out, optional] PBYTE PropertyBuffer 指向接收正在检索的属性的缓冲区的指针
[in] DWORD PropertyBufferSize 缓冲区大小
[out, optional] PDWORD RequiredSize 缓冲区的所需大小。可为NULL(可选)

程序中设备属性设置为SPDRP_DEVICEDESC,查询的是设备名的描述,还有很多属性参见

MSDN页面-SetupDiGetDeviceRegistryPropertyW

需要注意的是

  • windows API 通常分单双字节版本,单字节版本一般调用A结尾的API,对应的VS项目属性中字符集为Multi-Byte,双字节版本一般调用以w结尾的API,对应VS项目属性中字符集为Unicode。本例项目属性为Unicode,对应双字节字符串版本,所以输出信息以wcout输出,缓冲区指针转换为wchar_t*
  • TCHAR为自动根据项目中字符集属性转为char(Multi-Byte)或wchar(Unicode)

Windows下获取设备管理器列表信息-setupAPI的更多相关文章

  1. windows下获取IP地址的两种方法

    windows下获取IP地址的两种方法: 一种可以获取IPv4和IPv6,但是需要WSAStartup: 一种只能取到IPv4,但是不需要WSAStartup: 如下: 方法一:(可以获取IPv4和I ...

  2. c和c++在windows下获取时间和计算时间差的方法总结

    c/c++在windows下获取时间和计算时间差的几种方法总结 一.标准C和C++都可用 1.获取时间用time_t time( time_t * timer ),计算时间差使用double diff ...

  3. Windows下获取本机IP地址方法介绍

    Windows下获取本机IP地址方法介绍 if((hostinfo = gethostbyname(name)) != NULL) { #if 1 ; printf("IP COUNT: % ...

  4. Windows下获取高精度时间注意事项

    Windows下获取高精度时间注意事项 [转贴 AdamWu]   花了很长时间才得到的经验,与大家分享. 1. RDTSC - 粒度: 纳秒级 不推荐优势: 几乎是能够获得最细粒度的计数器抛弃理由: ...

  5. C语言实现Windows下获取IP和MAC地址。

    C语言实现Windows下获取IP和MAC地址. #include <winsock2.h> #include <stdio.h> #include <stdlib.h& ...

  6. 【转载】c/c++在windows下获取时间和计算时间差的几种方法总结

    一.标准C和C++都可用 1.获取时间用time_t time( time_t * timer ),计算时间差使用double difftime( time_t timer1, time_t time ...

  7. Windows 下获取硬盘序列号

    只获取序列号 以下任意一条命令都可以: wmic diskdrive get serialnumber wmic path win32_physicalmedia get SerialNumber w ...

  8. c/c++在windows下获取时间和计算时间差的几种方法总结 【转】

    http://blog.csdn.net/coder_xia/article/details/6566708 一.标准C和C++都可用 1.获取时间用time_t time( time_t * tim ...

  9. iOS6.0下获取通讯录用户列表

    自iOS6.0后获取通讯录列表需要询问用户,经过用户同意后才可以获取通讯录用户列表.而且ABAddressBookRef的初始化工作也由ABAddressBookCreate函数转变为ABAddres ...

  10. 让Windows下的Tomcat将控制台信息记录到日志

    在开发的过程中经常出现包冲突,却不知道怎么回事,可以在 catalina.bat 里面设置查看class加载日志   set CATALINA_OPTS=-server -Xdebug -Xnoage ...

随机推荐

  1. Java中各种比较对象方式对比

    1.介绍 比较对象是面向对象编程语言的一个基本特征.在本教程中,我们将介绍Java语言的一些特性,这些特性允许我们比较对象.此外,我们还将研究外部库中的这些特性. 2.==和!=操作符 让我们从==和 ...

  2. Python之机器人卡牌

    介绍 这个例子主要利用turtle库实现根据输入动态展示不同机器人的图像和属性信息. 代码部分非原创只是做了些许修改和整理使得更易阅读. 图片和文件资源请访问git仓库获取: https://gite ...

  3. django学习第十四天--Forms和ModelForm

    Forms和ModelForm 进行数据校验,先看数据校验的过程 注册页面图解: 前端为了用户体验会做一些校验,不满足校验要求会报错 服务端也会对数据进行一些校验,不满足校验要求会报错 数据库也会对数 ...

  4. django时区相关说明

    # naive time 从字面意思上理解,这是个"幼稚的时间",所以可以理解为它是个本地时间,不带时区信息,不能直接用于存储,如下 import datetime datetim ...

  5. 【Azure Batch】在中国区批处理服务(Mooncake Batch Account)上实验自动池(Auto Pool)的创建/删除

    问题描述 在Azure Batch的介绍文档中,提出了自动池的概念, 它可以在任务完成后,自动删除Pool资源,详细介绍:https://docs.azure.cn/zh-cn/batch/nodes ...

  6. Alertmanager钉钉告警

    一.部署alertmanager 1.1 创建目录 mkdir -p /deploy/app/alertmanager/config chmod -R 777 /deploy/app/alertman ...

  7. RPA能否创造新业态?如何优化组织结构?如何助力疫情中的企业?

    RPA能否创造新业态?如何优化组织结构?如何助力疫情中的企业? 从<爱,死亡和机器人>探讨强人工智能时代的RPA发展 文/王吉伟 本周四,王吉伟频道参加了私域流量社群的一个直播活动. 活动 ...

  8. c 语言默认什么编码

    C语言是没有编码的.它的编码就是平台的默认编码.比方说在windows 上汉字编码用gb2312 或者 说cp936(GBK一般的windows默认代码页,windows分为不同的代码页,可以查看一下 ...

  9. python中记录打印的log模块logging的用法实例

    日志基础教程   日志是对软件执行时所发生事件的一种追踪方式.软件开发人员对他们的代码添加日志调用,借此来指示某事件的发生.一个事件通过一些包含变量数据的描述信息来描述(比如:每个事件发生时的数据都是 ...

  10. 一次对requirements环境的配置

    事情是这样的,我需要跑通一个代码,因此要配置环境,但是并不能利用requirements中给的指令直接配置,于是开始找一些其他的解决方法.作为一名小白,总是绕很多弯路. 记下一些蜿蜒. 首先,摘录re ...