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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/53559.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分布式技术概览

文章目录 分布式技术1. 分布式数据库&#xff08;Distributed Databases&#xff09;2. 分布式文件系统&#xff08;Distributed File Systems&#xff09;3. 分布式哈希表&#xff08;Distributed Hash Tables, DHTs&#xff09;4. 分布式缓存&#xff08;Distributed Caching…

面试必问:Java 类加载过程

java 类加载过程主要分为加载、链接和初始化三个阶段&#xff0c;六个关键步骤&#xff1a;加载、验证、准备、解析、初始化。 加载阶段&#xff08;Loading&#xff09; 加载时类加载的第一个过程&#xff0c;在这个阶段&#xff0c;将完成以下三件事情&#xff1a; 1&#…

基于Springboot的鲜花销售网站的设计与实现

项目描述 这是一款基于Springboot的鲜花销售网站的系统 模块描述 鲜花销售系统 1、用户 登录 在线注册 浏览商品 鲜花搜索 订购商品 查询商品详情 水果分类查看 水果加购物车 下单结算 填写收货地址 2、管理员 登录 用户管理 商品管理 订单管理 账户管理 截图

项目经理应该学习pmp还是cspm?

职场竞争激烈&#xff0c;项目管理专业人才在各个行业中的作用越来越凸显出来。在23年之前&#xff0c;我国关于通用项目管理人才的培养更多依赖于国外的PMP认证&#xff0c;缺少自主的认证评价标准和体系。 为了弥补这一空缺&#xff0c;基于国内的项目管理发展需求&#xff…

西门子博途零基础学PLC必会的100个指令

#西门子##PLC##自动化##工业自动化##编程##电工##西门子PLC##工业##制造业##数字化##电气##工程师# 工控人加入PLC工业自动化精英社群 工控人加入PLC工业自动化精英社群

OpenMV——色块追踪

Python知识&#xff1a; 1.给Python的列表赋值&#xff1a; 定义一个元组时就是 元组a (1,2,…) 元组中可以只有一个元素&#xff0c;但是就必须要加一个 “ , ” 如 a (2,) 而列表的定义和元组类似&#xff0c;只是把()换成[]: #那么下面的colour_1 ~ 3属于元组&#xf…

(计算机网络)运输层

一.运输层的作用 运输层&#xff1a;负责将数据统一的交给网络层 实质&#xff1a;进程在通信 TCP&#xff08;有反馈&#xff09;UDP&#xff08;无反馈&#xff09; 二.复用和分用 三. TCP和UDP的特点和区别 进程号--不是固定的 端口号固定--mysql--3306 端口--通信的终点 …

苹果的“AI茅”之路只走了一半

今年苹果发布会最大的亮点&#xff0c;也许是和华为“撞档”&#xff0c;又或者是替腾讯“发布”新手游&#xff0c;但肯定不是iPhone 16。 9月10日&#xff0c;苹果秋季新品发布会与华为见非凡品牌盛典相继举行&#xff0c;iPhone 16系列也与HUAWEI Mate XT同日发布。 不过&…

传统CV算法——特征匹配算法

Brute-Force蛮力匹配 Brute-Force蛮力匹配是一种简单直接的模式识别方法&#xff0c;经常用于计算机视觉和数字图像处理领域中的特征匹配。该方法通过逐一比较目标图像中的所有特征点与源图像中的特征点来寻找最佳匹配。这种方法的主要步骤包括&#xff1a; 特征提取&#xff…

根据NVeloDocx Word模板引擎生成Word(三)

基于永久免费开放的《E6低代码开发平台》的Word模版引擎NVeloDocx&#xff0c;实现根据Word模版生成Word文件&#xff0c;前面2篇已经非常详细介绍了《主表单字段》&#xff0c;《子表记录循环输入到表格》。那这一篇我们就介绍插入单张图片、二维码&#xff0c;条形码等等&…

python-网页自动化(三)

如果遇到使用 ajax 加载的网页&#xff0c;页面元素可能不是同时加载出来的&#xff0c;这个时候尝试在 get 方法执行完 成时获取网页源代码可能并非浏览器完全加载完成的页面。所以&#xff0c;这种情况下需要设置延时等待一定时间&#xff0c;确保全部节点都加载出来。 那么&…

【Petri网导论学习笔记】Petri网导论入门学习(一)

Petri 网导论 如需学习转载请注明原作者并附本帖链接&#xff01;&#xff01;&#xff01; 如需学习转载请注明原作者并附本帖链接&#xff01;&#xff01;&#xff01; 如需学习转载请注明原作者并附本帖链接&#xff01;&#xff01;&#xff01; 发现网上关于Petri网的学习…

【机器学习】从零开始理解深度学习——揭开神经网络的神秘面纱

1. 引言 随着技术的飞速发展,人工智能(AI)已从学术研究的实验室走向现实应用的舞台,成为推动现代社会变革的核心动力之一。而在这一进程中,深度学习(Deep Learning)因其在大规模数据处理和复杂问题求解中的卓越表现,迅速崛起为人工智能的最前沿技术。深度学习的核心是…

金智维K-RPA基本介绍

一、K-RPA基本组成 K-RPA软件机器人管理系统基于“RPAX”数字化技术打造&#xff0c;其核心系统由管理中心(Server)、设计器(Control)、机器人(Robot/Agent)三大子系统组成&#xff0c;各子系统协同工作&#xff0c;易于构建协同式环境。 管理中心&#xff08;Server&#xff…

【Linux 运维知识】Linux 编译后的内核镜像大小

Linux 内核镜像的大小取决于多个因素&#xff0c;包括内核的版本、启用的功能、模块的数量以及特定的编译配置。 以下是常见情况下不同内核镜像的大小范围&#xff1a; 1. 标准内核镜像大小 压缩后的内核镜像 (vmlinuz)&#xff1a; 压缩后的内核镜像文件&#xff0c;通常位于…

基于boost的共享内存通信demo

文章目录 前言一、共享内存管理二、图像算法服务中的IPC通信流程三、demo实验结果总结 前言 在一个系统比较复杂的时候&#xff0c;将模块独立成单独的进程有助于错误定位以及异常重启恢复&#xff0c;不至于某个模块发生崩溃导致整个系统崩溃。当通信数据量比较大时&#xff…

AI视频生成-一键创作动漫

一、前言 随着深度学习技术和计算能力的进步&#xff0c;AI生成视频&#xff08;AIGV&#xff09;已经从一个研究概念演变成了一种实用工具&#xff0c;其应用场景也在不断拓展。从自动合成新闻报道到虚拟人物的互动视频&#xff0c;从电影特效生成到游戏场景的实时渲染&#…

C++基础知识6 vector

vector 1.vector的介绍及使用1.1 vector的介绍1.2 vector的使用1.2.1 vector的定义1.2.2 vector iterator 的使用1.2.3 vector 常用的接口1.2.4 vector 空间增长问题1.2.4 vector 迭代器失效问题。&#xff08;重点&#xff09; 2.vector模拟实现 1.vector的介绍及使用 1.1 ve…

Dubbo精要

1、为什么需要 Dubbo&#xff1f; 分布式系统中的服务调用和协调问题&#xff1a;在分布式系统中&#xff0c;服务之间的相互依赖会导致复杂的通信和协调问题。Dubbo提供了高效的服务调用和自动注册、发现等功能&#xff0c;使得构建分布式应用程序更加容易。服务治理和服务调…

局域网设备自动发现常用方法

文章目录 需求实现方法ARP (Address Resolution Protocol)Ping ip的流程抓包如下代码实现 mDNS 对比测试Avahi 介绍Avahi 安装Avahi 使用测试代码 需求 局域网设备自动发现是软件开发中的一个常见且重要的需求&#xff0c;它简化了设备间的协作机制&#xff0c;降低了软件各模…