当前位置: 首页 > news >正文

Qt篇——Qt使用C++获取Windows电脑上所有外接设备的名称、物理端口位置等信息

        我之前有发过一篇文章《Qt篇——获取Windows系统上插入的串口设备的物理序号》,文章中主要获取的是插入的USB串口设备的物理序号;而本篇文章则进行拓展,可以获取所有外接设备的相关信息(比如USB摄像头、USB蓝牙、USB网卡、其它一些可拔插的设备等等),并且代码进行了优化、精简。代码如下,可直接cv享用。(代码中有一段筛选相机设备的代码被注释掉了,如果你仅仅只需要获取到相机的设置信息,可以取消注释。)

#include <QDebug>
#include <windows.h>
#include <setupapi.h>
#include <devguid.h>#pragma comment(lib, "setupapi.lib")void DevicesTool::listCameras() {// 获取所有图像设备, GUID_DEVCLASS_USB、GUID_DEVCLASS_SYSTEM等等都可以,根据实际需求选择HDEVINFO deviceInfoSet = SetupDiGetClassDevs(&GUID_DEVCLASS_USB, nullptr, nullptr, DIGCF_PRESENT | DIGCF_ALLCLASSES);if (deviceInfoSet == INVALID_HANDLE_VALUE) {qDebug() << "Failed to get device info set";return;}SP_DEVINFO_DATA deviceInfoData;deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);// 遍历设备列表for (DWORD i = 0; SetupDiEnumDeviceInfo(deviceInfoSet, i, &deviceInfoData); i++) {TCHAR deviceName[256];QString deviceDescStr = "", deviceNameStr = "", deviceLocationInfoStr = "", deviceLocationPathStr;if (SetupDiGetDeviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_DEVICEDESC, nullptr,(PBYTE)deviceName, sizeof(deviceName), nullptr)) {deviceDescStr= QString::fromWCharArray(deviceName);}if (SetupDiGetDeviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_FRIENDLYNAME, nullptr,(PBYTE)deviceName, sizeof(deviceName), nullptr)) {deviceNameStr = QString::fromWCharArray(deviceName);}if (SetupDiGetDeviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_LOCATION_INFORMATION, nullptr,(PBYTE)deviceName, sizeof(deviceName), nullptr)) {deviceLocationInfoStr = QString::fromWCharArray(deviceName);}if (SetupDiGetDeviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_LOCATION_PATHS, nullptr,(PBYTE)deviceName, sizeof(deviceName), nullptr)) {deviceLocationPathStr = QString::fromWCharArray(deviceName);}if (deviceLocationInfoStr != "" && deviceDescStr != "" && deviceNameStr != "" && deviceLocationPathStr != "") {qDebug() << "Device: " << deviceDescStr << deviceNameStr << deviceLocationInfoStr << deviceLocationPathStr;}//如果只需要USB相机设备的信息,可以再筛选一条属性//index值越小代表着用opencv的VideoCapture.open()里面的相机序号越靠前
/**int index = -1;if (SetupDiGetDeviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_DRIVER, nullptr,(PBYTE)deviceName, sizeof(deviceName), nullptr)) {index = QString::fromWCharArray(deviceName).split("\\")[1].toInt();}if (deviceLocationInfoStr != "" && deviceDescStr != ""&& deviceNameStr != "" && deviceLocationPathStr != "" && index != -1) {qDebug() << "Device: " << deviceDescStr << deviceNameStr << deviceLocationInfoStr << deviceLocationPathStr << index;cameraList.append(new DeviceInfo(deviceNameStr, deviceDescStr, deviceLocationInfoStr, deviceLocationPathStr, index));}
*/}SetupDiDestroyDeviceInfoList(deviceInfoSet);
}

打印结果如下:

 比如我获取到的4个USB 视频设备就是我插入的3个USB相机、系统自带的相机,这里就可以知道哪个相机插在哪个USB口上面了(右键此电脑-管理-设备管理器-照相机,双击我要查看的相机,里面的“位置”就是上面代码中获取到的deviceLocationInfoStr)。

        ps:其实还有更多设备信息可以查看,只是我打印的地方进行了筛选,只有4项信息(物理端口信息、物理端口路径、设备信息、设备名称)都能够获取的才进行打印,可以根据你实际需求降低筛选。 

需要了解代码原理的看这里,这里简单地介绍各个函数的用途:

1.SetupDiGetClassDevs函数返回一个包含本机上所有被请求的设备信息的设备信息集合句柄。

HDEVINFO SetupDiGetClassDevs(_In_opt_ const GUID   *ClassGuid, // 一个指向GUID的指针,此GUID可标识一个设备安装类或一个设备接口类, 可以为NULL_In_opt_       PCTSTR Enumerator, // 一个指向以空字符结束的字符串的指针_In_opt_       HWND   hwndParent, // 用于与在设备信息集中安装设备实例相关联的用户界面的顶级窗口句柄_In_           DWORD  Flags       // 通过此参数来过滤指定的设备信息集中的设备, DIGCF_PRESENT表示只返回当前系统中存在的(已连接)设备。
);

        该函数的第一个入口参数GUID指定了我们想要检索什么类型的设备,一些常用的GUID如下:

GUID_DEVCLASS_SYSTEM    // 系统设备GUID
GUID_DEVCLASS_USB       // USB设备GUID
GUID_DEVCLASS_MOUSE     // 鼠标设备GUID
GUID_DEVCLASS_NET       // 网络设备GUID
GUID_DEVCLASS_KEYBOARD  // 键盘设备GUID

        当调用完此函数并处理完相应数据后,必须调用SetupDiDestroyDeviceInfoList函数,否则内存溢出。

2.SetupDiEnumDeviceInfo函数返回一个SP_DEVINFO_DATA结构,它指定该设备的信息集的设备的信息元素。

BOOL SetupDiEnumDeviceInfo(_In_ HDEVINFO DeviceInfoSet,          // 设备信息集的句柄,即SetupDiGetClassDevs返回的句柄_In_ DWORD MemberIndex,               // 要检索的设备信息元素的从零开始的索引_Out_ PSP_DEVINFO_DATA DeviceInfoData // 指向SP_DEVINFO_DATA结构的指针,以接收有关枚举设备信息元素的信息);

3.SetupDiGetDeviceRegistryProperty检索指定的即插即用设备属性.

BOOL SetupDiGetDeviceRegistryPropertyW(_In_ HDEVINFO DeviceInfoSet,          // 设备信息集的句柄,即SetupDiGetClassDevs返回的句柄_In_ PSP_DEVINFO_DATA DeviceInfoData, // 指向SP_DEVINFO_DATA结构的指针,该结构指定DeviceInfoSet中的设备信息元素_In_ DWORD Property,                  // 指定要检索的属性_Out_opt_ PDWORD PropertyRegDataType, // 指向一个变量的指针,该变量接收要检索的属性的数据类型。_Out_writes_bytes_to_opt_(PropertyBufferSize, *RequiredSize) PBYTE PropertyBuffer, // 指向缓冲区的指针,该缓冲区接收正在检索的属性_In_ DWORD PropertyBufferSize,        // PropertyBuffer缓冲区的大小(单位:字节)_Out_opt_ PDWORD RequiredSize         // 指向DWORD类型的变量的指针,该变量接收所需的PropertyBuffer缓冲区的大小(单位:字节));

        该函数的第三个入口参数Property决定了我们想要检索设备的什么属性,它的取值可以在SetupAPI.h文件里查找,一些常用的属性的含义如下:

#常用
#define SPDRP_DEVICEDESC                  (0x00000000)  // DeviceDesc (R/W)
#define SPDRP_FRIENDLYNAME                (0x0000000C)  // FriendlyName (R/W)
#define SPDRP_LOCATION_INFORMATION        (0x0000000D)  // LocationInformation (R/W)#其他
#define SPDRP_HARDWAREID                  (0x00000001)  // HardwareID (R/W)
#define SPDRP_COMPATIBLEIDS               (0x00000002)  // CompatibleIDs (R/W)
#define SPDRP_CLASS                       (0x00000007)  // Class (R--tied to ClassGUID)
#define SPDRP_CLASSGUID                   (0x00000008)  // ClassGUID (R/W)

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Java飞越爱河情侣专属飞行棋系统小程序源码
  • IPv6理论基础
  • C/C++ let __DATE__ format to “YYYY-MM-DD“
  • Ionic 头部和底部
  • C++ | Leetcode C++题解之第397题整数替换
  • Linux 远程连接与常见错误:一直输入密码,无报错或无填充
  • 通杀漏洞挖掘 | 某系统超级管理员任意密码重置
  • strcmp函数的使用和模拟实现
  • 台球助教小程序开发/APP源码部署
  • vue页面使用自定义字体
  • Redis:缓存击穿
  • 低空经济新概念
  • 1 Linux SSH安全加固_linux system-auth
  • HTML 基础,尚优选网站设计开发(二)
  • 数据结构应用实例(四)——最小生成树
  • Docker 笔记(2):Dockerfile
  • HTML-表单
  • JDK9: 集成 Jshell 和 Maven 项目.
  • node-glob通配符
  • SpiderData 2019年2月16日 DApp数据排行榜
  • 聊聊flink的TableFactory
  • 前言-如何学习区块链
  • 如何优雅地使用 Sublime Text
  • 三栏布局总结
  • 一些关于Rust在2019年的思考
  • 应用生命周期终极 DevOps 工具包
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • 第二十章:异步和文件I/O.(二十三)
  • #include
  • #Z2294. 打印树的直径
  • #大学#套接字
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • (2024,Vision-LSTM,ViL,xLSTM,ViT,ViM,双向扫描)xLSTM 作为通用视觉骨干
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (附源码)ssm本科教学合格评估管理系统 毕业设计 180916
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (六)c52学习之旅-独立按键
  • **python多态
  • .net framework 4.0中如何 输出 form 的name属性。
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .NET中winform传递参数至Url并获得返回值或文件
  • .NET中的Exception处理(C#)
  • @cacheable 是否缓存成功_Spring Cache缓存注解
  • @JsonSerialize注解的使用
  • @Transactional 参数详解
  • [ 数据结构 - C++] AVL树原理及实现
  • [2013AAA]On a fractional nonlinear hyperbolic equation arising from relative theory
  • [Android Studio] 开发Java 程序
  • [BFS广搜]迷阵
  • [C++] C++11详解 (一)
  • [C++] 深入理解面向对象编程特性 : 继承
  • [C++]C++基础知识概述
  • [CC-FNCS]Chef and Churu