本文Jungle将用vs2013+Qt5.6.0来实现设备管理器。什么是设备管理器?使用过Windows系统的人应该不陌生,它用来管理计算机上的设备。可以使用“设备管理器”查看和更改设备属性、更新设备驱动、配置设备和卸载设备,如下图:

外观上来说,设备管理器提供计算机上所安装硬件的图形视图。所以本节Jungle要设计的设备管理器也只是实现这样一个能够显示计算机上所安装硬件的视图软件

1.开发环境

vs2013+Qt5.6.0

2.UI设计

本设计的UI很简单,主要由QTreeView和QTextEdit两个控件组成:

  • QTreeView:以树形列表的形式按照设备类型枚举出计算机上所连接的各类设备
  • QTextEdit:当鼠标点击到设备列表上的某个设备时,该控件打印出该设备的具体信息,比如GUID、PID、VID等。

3.主要API介绍

3.1.Windows API

Windows API主要用于获取指定设备类的指定属性

3.1.1. SetupDiGetClassDevs

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

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

该函数的第一个入口参数GUID指定了我们想要检索什么类型的设备,它的取值可以在devguid文件中查找,这里不一一列举。本例中会只用到以下GUID,它们的含义如下:

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

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

3.1.2.SetupDiEnumDeviceInfo

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

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

3.1.3.SetupDiGetDeviceRegistryProperty

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文件里查找,这里不一一列举。比如本例中会用到下述Property,它们的含义如下:

#define SPDRP_DEVICEDESC                  (0x00000000)  // DeviceDesc (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)

3.2.Qt相关控件

3.2.1.QTreeView

QTreeView类提供树视图的默认模型/视图实现。QTreeView实现了模型中项目的树形表示。关于这个控件的使用方式,比如添加条目(Item)、设置条目图片等在代码里会体现,也可以自己查询Qt Assistant。

比较重要的是本例中用到的QTreeView的一个信号槽函数。当鼠标点击到设备树上的某个设备时,我们需要知道鼠标点击的设备属于什么类型(USB设备?键盘类?鼠标类?),即要知道被点击的节点的父节点是谁。另一方面,也需要知道被点击的节点在该类设备中的索引。所以在本例中我们有以下的信号槽连接:

connect(ui.treeView, SIGNAL(clicked(const QModelIndex)), this, SLOT(getTreeClicked(const QModelIndex)));

其中:

  • ui.treeView:即UI上的QTreeView控件
  • SIGNAL:信号,当设备树上某个节点被鼠标点击时,会自动emit信号
  • SLOT:槽函数,Jungle自己定义实现的处理函数,根据QModelIndex获取父节点和该节点索引

3.2.2.QTimer

定时器,定时刷新设备树。计算机上连接的设备可能会动态改变,比如插拔USB设备。关于QTimer的使用在此也不详述。本例中有以下信号槽连接:

connect(timer, SIGNAL(timeout()), this, SLOT(refreshTree()));

其中,timer是全局的QTimer对象。信号timeout表示定时器溢出时自动发出的信号,溢出频率可以通过QTimer的setInterval函数设定。槽函数refreshTree()是Jungle自己定义实现的,从函数名字可以知道,每次定时器溢出时,将会刷新设备树

4.程序结构

本例的程序结构图如下:

4.1.UsbViewerQt

UsbViewerQt是主要的框架类,处理UI事务和功能事务。这里的UI事务是指用户与软件界面的交互,比如鼠标点击的活动;功能事务是指调用对应接口检索设备信息。UsbViewerQt的作用即是衔接UI事务和功能事务。

从上面的类图中可以看到,类UsbViewerQt有几个QStringList对象,分别用于保存各类设备下子设备的描述信息。LOG类对象log用于为整个程序提供日志功能,关于这部分,详见4.3。接口initTreeModel()完成初始化工作;refreshDeviceList()用于周期刷新设备列表;getHostName()用于获取主机名称,显示在设备树根节点上。

4.2.UsbInterface

UsbInterface并不是一个类,而是用纯C语言实现的检索指定设备类的各类属性的接口,为框架类对象UsbViewerQt服务。为了使用方便,Jungle定义了与Windows API适配的一个枚举:

enum DeviceClass{DeviceClass_NONE = -1,DeviceClass_MOUSE,DeviceClass_SYSTEM,DeviceClass_USB,DeviceClass_NET,DeviceClass_KEYBOARD
};

4.3.LOG

这是Jungle自行设计实现的一个日志系统,方便调试跟踪程序运行状况,设计语言为C++。这部分内容可以参见Jungle的博客:C++设计实现日志系统。源码可以在Github上获取:https://github.com/FengJungle/Log

5.实现

5.1.UsbQtViewer

头文件:

class UsbViewerQt : public QMainWindow
{Q_OBJECTpublic:UsbViewerQt(QWidget *parent = 0);~UsbViewerQt();// Init treeModelvoid initTreeModel();// Refresh the device listvoid refreshDeviceList(DeviceClass deviceClass, QStandardItem* deviceTreeRoot);// Retrieve the host nameQString getHostName();// timerQTimer* timer;public slots:// slots: when the tree is clickedvoid getTreeClicked(const QModelIndex index);// slots: refresh tree when timer timeoutvoid refreshTree();private:Ui::UsbViewerQtClass ui;QTreeView* pTreeView;// UI tree root modelQStandardItemModel* rootModel;// Usb device info list QStringList usbInfoList;// System device info list QStringList systemInfoList;// Mouse device info listQStringList mouseInfoList;// Net device info listQStringList netInfoList;// Keyboard device info listQStringList keyBoardInfoList;// LoggerLOG* Log;
};

源文件:

#include "UsbViewerQt.h"#include <QtNetwork\qhostinfo.h>UsbViewerQt::UsbViewerQt(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);setWindowIcon(QIcon("Icon/Token.png"));rootModel = NULL;// LogLog = LOG::getInstance();// Init tree viewinitTreeModel();// Timerthis->timer = new QTimer(this);//timer->start();timer->setInterval(1000);connect(ui.treeView, SIGNAL(clicked(const QModelIndex)), this, SLOT(getTreeClicked(const QModelIndex)));connect(timer, SIGNAL(timeout()), this, SLOT(refreshTree()));
}UsbViewerQt::~UsbViewerQt()
{}void UsbViewerQt::initTreeModel()
{ENTER();QTreeView * tree = ui.treeView;// Root Treeif (rootModel == NULL){this->rootModel = new QStandardItemModel();tree->setModel(rootModel);}else{rootModel->clear();}QStandardItem * rootStandardItem = rootModel->invisibleRootItem();QStandardItem* rootItem = new QStandardItem(getHostName());rootStandardItem->appendRow(rootItem);// USB device Root Tree QStandardItem* usbTreeRoot = new QStandardItem(QIcon("Icon/USB.png"), tr("USB")); rootItem->appendRow(usbTreeRoot);refreshDeviceList(DeviceClass_USB, usbTreeRoot);// System device Root Tree QStandardItem* systemDeviceTreeRoot = new QStandardItem(QIcon("Icon/SystemDevice.png"), tr("SystemDevice"));rootItem->appendRow(systemDeviceTreeRoot);refreshDeviceList(DeviceClass_SYSTEM, systemDeviceTreeRoot);// Mouse Root Tree QStandardItem* mouseTreeRoot = new QStandardItem(QIcon("Icon/Mouse.png"), tr("Mouse"));rootItem->appendRow(mouseTreeRoot);refreshDeviceList(DeviceClass_MOUSE, mouseTreeRoot);// Net Root Tree QStandardItem* netTreeRoot = new QStandardItem(QIcon("Icon/Net.png"), tr("Net"));rootItem->appendRow(netTreeRoot);refreshDeviceList(DeviceClass_NET, netTreeRoot);// keyboard Root Tree QStandardItem* keyboardTreeRoot = new QStandardItem(QIcon("Icon/Keyboard.png"), tr("Keyboard"));rootItem->appendRow(keyboardTreeRoot);refreshDeviceList(DeviceClass_KEYBOARD, keyboardTreeRoot);EXIT();
}QString UsbViewerQt::getHostName()
{ENTER();QString hostName = QHostInfo::localHostName();return hostName;
}void UsbViewerQt::refreshDeviceList(DeviceClass deviceClass, QStandardItem* deviceTreeRoot)
{ENTER();// Retrieve all device infochar deviceInfo[10000] = { 0 };int res = getDeviceProperty(deviceClass, Property_DESCRIPTION, INDEX_ALL, deviceInfo);QString DeviceInfoStr = QString::fromLocal8Bit(deviceInfo);QStringList deviceInfoList = DeviceInfoStr.split("\n");deviceInfoList.removeAt(deviceInfoList.size() - 1);QString IconPath;switch (deviceClass){case DeviceClass_SYSTEM:IconPath = "Icon/SystemDevice.png";this->systemInfoList = deviceInfoList;break;case DeviceClass_USB:IconPath = "Icon/USB.png";this->usbInfoList = deviceInfoList;break;case DeviceClass_MOUSE:IconPath = "Icon/Mouse.png";this->mouseInfoList = deviceInfoList;break;case DeviceClass_NET:IconPath = "Icon/Net.png";this->netInfoList = deviceInfoList;break;case DeviceClass_KEYBOARD:IconPath = "Icon/Keyboard.png";this->keyBoardInfoList = deviceInfoList;break;default:break;}for (int index = 0; index <deviceInfoList.count(); index++){QString iName = deviceInfoList[index];QStandardItem * item = new QStandardItem(QIcon(IconPath), iName);deviceTreeRoot->appendRow(item);}ui.treeView->expandAll();EXIT();
}void UsbViewerQt::getTreeClicked(const QModelIndex iIndex)
{ENTER();// 1. Retrieve current selected itemQString objectName = ui.treeView->model()->itemData(iIndex).values()[0].toString();// 2. Get the father item to distinguish the device classQStandardItem* parentItem = this->rootModel->itemFromIndex(iIndex)->parent();QString parentItemText = parentItem->text();QByteArray ba_objectName = objectName.toLocal8Bit();QByteArray ba_parentItemText = parentItemText.toLatin1();LOG_DEBUG("Selected device: %s", ba_objectName.data());LOG_DEBUG("The selected device' class is %s", ba_parentItemText.data());DeviceClass deviceClass;QStringList deviceInfoList;if (parentItemText == "USB"){deviceInfoList = this->usbInfoList;deviceClass = DeviceClass_USB;}else if (parentItemText == "SystemDevice"){deviceInfoList = this->systemInfoList;deviceClass = DeviceClass_SYSTEM;}else if (parentItemText == "Mouse"){deviceInfoList = this->mouseInfoList;deviceClass = DeviceClass_MOUSE;}else if (parentItemText == "Net"){deviceInfoList = this->netInfoList;deviceClass = DeviceClass_NET;}else if (parentItemText == "Keyboard"){deviceInfoList = this->keyBoardInfoList;deviceClass = DeviceClass_KEYBOARD;}else{ui.textEdit->clear();return;}// 3. Retrieve the device index with object nameint index = 0;for (index; index < deviceInfoList.size(); index++){if (deviceInfoList[index] == objectName){break;}}// 4. Retrieve the device detailed info with the indexchar buffer[1024] = { 0 };int ret = getDeviceProperty(deviceClass, Property_DESCRIPTION, index, buffer);QString result = QString::fromLocal8Bit(buffer);ui.textEdit->setText(result);EXIT();
}void UsbViewerQt::refreshTree()
{initTreeModel();
}

5.2.UsbInterface

头文件:

#ifndef _USBINTERFACE_H_
#define _USBINTERFACE_H_#define INDEX_ALL -1enum DeviceClass{DeviceClass_NONE = -1,DeviceClass_MOUSE,DeviceClass_SYSTEM,DeviceClass_USB,DeviceClass_NET,DeviceClass_KEYBOARD
};enum Property{Property_NONE          = -1,Property_DESCRIPTION   = 0x00000000,Property_HARDWAREID    = 0x00000001,Property_COMPATIBLEIDS = 0x00000002
};/*
* Function:      getDeviceProperty
* Description:   obtain appointed device's property and save it in the buffer
* Para:          deviceClass    - specific device class
*                deviceProperty - specific device property intended to retrieve
*                index          - device index in the deviceInfoSet
*                buffer         - buffer saved the retieved device property
* Return:        success return 0, or other error code
* Author:        fengqiangguo
* Date:          2020-2-16
*/
int getDeviceProperty(DeviceClass deviceClass,Property    deviceProperty,int         index,char*       buffer);#endif //_USBINTERFACE_H_

源文件:

#include "UsbInterface.h"
#include "log.h"#include <Windows.h>
#include <SetupAPI.h>
#include <devguid.h>
#include <stdio.h>
#include <wchar.h>#pragma comment(lib, "setupapi.lib")int retrieveDeviceProperty(int         index,DeviceClass deviceClass,char*       buffer)
{ENTER();int res = 0;HDEVINFO hDevInfo;SP_DEVINFO_DATA DeviceInfoData = { sizeof(DeviceInfoData) };GUID guid;switch (deviceClass){case DeviceClass_SYSTEM:guid = GUID_DEVCLASS_SYSTEM;break;case DeviceClass_USB:guid = GUID_DEVCLASS_USB;break;case DeviceClass_MOUSE:guid = GUID_DEVCLASS_MOUSE;break;case DeviceClass_NET:guid = GUID_DEVCLASS_NET;break;case DeviceClass_KEYBOARD:guid = GUID_DEVCLASS_KEYBOARD;break;default:break;}// Get device class information set handle that contains requested device information elements for a local computerhDevInfo = SetupDiGetClassDevs(&guid,          0,              0,              DIGCF_PRESENT   );if (hDevInfo == INVALID_HANDLE_VALUE){res = GetLastError();return res;}// enumerute device informationDWORD required_size = 0;// SetupDiEnumDeviceInfo: returns a SP_DEVINFO_DATA structure that specifies a device information element in a device information setif (index == INDEX_ALL){for (int i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData); i++){DWORD DataT;wchar_t wcBuffer[2046] = { 0 };DWORD buffersize = 2046;DWORD req_bufsize = 0;char* asciiBuffer = NULL;// retrieves a specified Plug and Play device propertyif (!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_DEVICEDESC,&DataT,(LPBYTE)wcBuffer,buffersize,&req_bufsize)){res = GetLastError();//continue;}wideCharToASCII(wcBuffer, &asciiBuffer);strcat(asciiBuffer, "\n");strcat(buffer, asciiBuffer);}}else{SetupDiEnumDeviceInfo(hDevInfo, index, &DeviceInfoData);DWORD DataT;wchar_t wcBuffer[2046] = { 0 };DWORD buffersize = 2046;DWORD req_bufsize = 0;char* asciiBuffer = NULL;{// retrieve DESCRIPTIONLOG_DEBUG("retrieve DESCRIPTION");if (!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_DEVICEDESC,&DataT,(LPBYTE)wcBuffer,buffersize,&req_bufsize)){res = GetLastError();//continue;}char prefixBuffer[256] = "Device Description:\t";wideCharToASCII(wcBuffer, &asciiBuffer);strcat(asciiBuffer, "\n");strcat(prefixBuffer, asciiBuffer);strcat(buffer, prefixBuffer);}{// retrieve HARDWAREIDLOG_DEBUG("retrieve HARDWAREID");if (!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_HARDWAREID,&DataT,(LPBYTE)wcBuffer,buffersize,&req_bufsize)){res = GetLastError();//continue;}char prefixBuffer[256] = "Hardware ID:\t";wideCharToASCII(wcBuffer, &asciiBuffer);strcat(asciiBuffer, "\n");strcat(prefixBuffer, asciiBuffer);strcat(buffer, prefixBuffer);}{// retrieve COMPATIBLEIDSLOG_DEBUG("retrieve COMPATIBLEIDS");if (!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_COMPATIBLEIDS,&DataT,(LPBYTE)wcBuffer,buffersize,&req_bufsize)){res = GetLastError();//continue;}char prefixBuffer[256] = "Compatible ID:\t";wideCharToASCII(wcBuffer, &asciiBuffer);strcat(asciiBuffer, "\n");strcat(prefixBuffer, asciiBuffer);strcat(buffer, prefixBuffer);}{// retrieve SERVICELOG_DEBUG("retrieve SERVICE");if (!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_SERVICE,&DataT,(LPBYTE)wcBuffer,buffersize,&req_bufsize)){res = GetLastError();//continue;}char prefixBuffer[256] = "Service:\t\t";wideCharToASCII(wcBuffer, &asciiBuffer);strcat(asciiBuffer, "\n");strcat(prefixBuffer, asciiBuffer);strcat(buffer, prefixBuffer);}{// retrieve CLASSLOG_DEBUG("retrieve CLASS");if (!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_CLASS,&DataT,(LPBYTE)wcBuffer,buffersize,&req_bufsize)){res = GetLastError();//continue;}char prefixBuffer[256] = "Class:\t\t";wideCharToASCII(wcBuffer, &asciiBuffer);strcat(asciiBuffer, "\n");strcat(prefixBuffer, asciiBuffer);strcat(buffer, prefixBuffer);}{// retrieve CLASSGUIDLOG_DEBUG("retrieve CLASSGUID");if (!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_CLASSGUID,&DataT,(LPBYTE)wcBuffer,buffersize,&req_bufsize)){res = GetLastError();//continue;}char prefixBuffer[256] = "Class GUID:\t";wideCharToASCII(wcBuffer, &asciiBuffer);strcat(asciiBuffer, "\n");strcat(prefixBuffer, asciiBuffer);strcat(buffer, prefixBuffer);}{// retrieve DRIVERLOG_DEBUG("retrieve DRIVER");if (!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_DRIVER,&DataT,(LPBYTE)wcBuffer,buffersize,&req_bufsize)){res = GetLastError();//continue;}char prefixBuffer[256] = "Driver:\t\t";wideCharToASCII(wcBuffer, &asciiBuffer);strcat(asciiBuffer, "\n");strcat(prefixBuffer, asciiBuffer);strcat(buffer, prefixBuffer);}{// retrieve MFGLOG_DEBUG("retrieve MFG");if (!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_MFG,&DataT,(LPBYTE)wcBuffer,buffersize,&req_bufsize)){res = GetLastError();//continue;}char prefixBuffer[256] = "MFG:\t\t";wideCharToASCII(wcBuffer, &asciiBuffer);strcat(asciiBuffer, "\n");strcat(prefixBuffer, asciiBuffer);strcat(buffer, prefixBuffer);}{// retrieve LOCATION_INFORMATIONLOG_DEBUG("retrieve LOCATION_INFORMATION");if (!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_LOCATION_INFORMATION,&DataT,(LPBYTE)wcBuffer,buffersize,&req_bufsize)){res = GetLastError();//continue;}char prefixBuffer[256] = "Location Information:\t";wideCharToASCII(wcBuffer, &asciiBuffer);strcat(asciiBuffer, "\n");strcat(prefixBuffer, asciiBuffer);strcat(buffer, prefixBuffer);}{// retrieve DEVICE_POWER_DATALOG_DEBUG("retrieve DEVICE_POWER_DATA");if (!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_DEVICE_POWER_DATA,&DataT,(LPBYTE)wcBuffer,buffersize,&req_bufsize)){res = GetLastError();//continue;}char prefixBuffer[256] = "Device Power Data:\t";wideCharToASCII(wcBuffer, &asciiBuffer);strcat(asciiBuffer, "\n");strcat(prefixBuffer, asciiBuffer);strcat(buffer, prefixBuffer);}{// retrieve FRIENDLYNAMELOG_DEBUG("retrieve FRIENDLYNAME");if (!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_FRIENDLYNAME,&DataT,(LPBYTE)wcBuffer,buffersize,&req_bufsize)){res = GetLastError();//continue;}char prefixBuffer[256] = "Friendly name:\t";wideCharToASCII(wcBuffer, &asciiBuffer);strcat(asciiBuffer, "\n");strcat(prefixBuffer, asciiBuffer);strcat(buffer, prefixBuffer);}{// retrieve LOCATION_PATHSLOG_DEBUG("retrieve LOCATION_PATHS");if (!SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_LOCATION_PATHS,&DataT,(LPBYTE)wcBuffer,buffersize,&req_bufsize)){res = GetLastError();//continue;}char prefixBuffer[256] = "Location path:\t";wideCharToASCII(wcBuffer, &asciiBuffer);strcat(asciiBuffer, "\n");strcat(prefixBuffer, asciiBuffer);strcat(buffer, prefixBuffer);}}SetupDiDestroyDeviceInfoList(&hDevInfo);EXIT();return res;
}int getDeviceProperty(DeviceClass deviceClass,Property    deviceProperty,int         index,char*       buffer)
{ENTER();int res = 0;if (deviceClass == DeviceClass_NONE || deviceProperty == Property_NONE){res = -1;goto exit;}if (nullptr == buffer){res = -2;goto exit;}res = retrieveDeviceProperty(index, deviceClass, buffer);exit:EXIT();return res;
}

5.3.LOG

该部分略,详见Github或者C++设计实现日志系统

6.效果

在工程路径的Log文件夹下可以看到日志文件UsbViewerQt.log:

7.源码获取和交流

源码地址:https://github.com/FengJungle/UsbViewer_Qt

欢迎和Jungle交流。

Qt实现设备管理器——枚举系统所有设备相关推荐

  1. win7移动设备管理器_win7系统usb设备识别不了的解决方案

    小编给大家浅析win7系统usb设备识别不了的解决方案,使用win7系统过程中,有时会遇到电脑无法识别USB设备的问题,遇到此问题的用户,请来看看下面的解决方案吧. 最近使用win7系统的用户就在跟小 ...

  2. 计算机管理-设备管理器没有找到打印机,win7系统设备管理器没有ieee1284.4设备的解决方法...

    本文教程小编和大家分享win7系统设备管理器没有ieee1284.4设备的解决方法,win7系统设备管理器是一种管理工具,可用它来管理计算机上的设备,占据着比较重要的位置.有些用户发现win7系统设备 ...

  3. 电脑无法显示移动硬盘盘符,在设备管理器里面的其他设备里面能够显示

    最近发现自己的笔记本无法读取移动硬盘,插上USB之后移动硬盘在正常运转,但是计算机上看不到任何新增盘符,但是在设备管理器里面的其他设备里面显示有该设备. 将移动硬盘插到另外的笔记本上可以正常显示,排除 ...

  4. Thinkpad安装系统后,在设备管理器中有一其他设备叹号为“PCI 数据捕获和信号处理控制器”...

    问题描述:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> T4 ...

  5. windows下枚举串口的方法,超好用,跟设备管理器枚举一样

     做上位机,与设备通信,经常会用到串口.看到一些串口助手,像SSCOM,能自动扫描枚举PC的串口.所以后面的应用,我也加上自动枚举串口.  在网上找的资料,最多的是读取注册表里的内容,HKEY_LOC ...

  6. win7 右键计算机 服务 设备管理器,win7系统计算机右键菜单添加设备管理器的操作方法...

    今天和大家分享一下关于对win7系统计算机右键菜单添加设备管理器设置的方法,在使用win7系统的过程中经常不知道如何去对win7系统计算机右键菜单添加设备管理器进行设置,有什么好的办法去设置win7系 ...

  7. 设备管理器出现“未知USB设备”同时蓝牙不可用的解决方法

      很莫名其妙地,刚才还在使用蓝牙鼠标和蓝牙键盘,离开一会儿后重新解锁进入桌面,蓝牙就彻底不见了.打开设备管理器,里面的蓝牙图标不见了,同时通用串行总线控制器中出现了一个未知USB设备.   查阅后找 ...

  8. 计算机设备管理没有其他设备,为何我的设备管理器里没有其他设备

    破记录的鸠 | 2009-08-14 11:44:28 有0人认为这个回答没有帮助 解法一:启动 Plug and Play 服务 单击开始,单击运行,键入 services.msc,然后单击确定. ...

  9. 计算机右击加设备管理器,win10系统计算机右键菜单添加设备管理器的还原步骤...

    win10系统使用久了,好多网友反馈说关于对win10系统计算机右键菜单添加设备管理器设置的方法,在使用win10系统的过程中经常不知道如何去对win10系统计算机右键菜单添加设备管理器进行设置,有什 ...

最新文章

  1. trash-cli设置Linux 回收站
  2. ActiveMQ高级特性
  3. gdal java shp_【GDAL/OGR】利用GDAL/OGR读取shp文件并转换为json文件(Java版)
  4. Linux环境安装python3.6(APT方式)
  5. Class.getResourceAsStream和ClassLoader.getResourceAsStream方法
  6. iOS 向下取整、向上取整、四舍五入
  7. 【转载】如何在归档后启用归档信息系统
  8. android wear评测,android wear5.1怎么样 android wear5.1更新评测
  9. 简单思维dp-- Gym - 102392B
  10. 经纬度绘图_用编程赋能工作系列——百度VS高德经纬度互转
  11. Android中Handler的使用方法——在子线程中更新界面
  12. 【每日算法Day 66】经典面试题:不用四则运算如何做加法?
  13. intellij idea 的常用有用快捷键
  14. 字节跳动-大数据研发面试准备
  15. 人工智能AI伪原创一键生成文章
  16. c语言实现 三角函数,关于数学:快速实现C ++三角函数
  17. 2014年东北四省赛总结
  18. (二)使用selenium爬取拉钩招聘网信息并存入csv文件
  19. Ed2k协议背景介绍及eMule协议的整体架构
  20. 15. 【C语言】Hanoi塔问题(Demo)

热门文章

  1. python绘制分形图形教程_python-图形绘制(1)-turtle-递归-分形几何美学-分形树
  2. echarts 3D折线图应用
  3. matlab规定形式化简多项式,如何用matlab化简多项式
  4. 雪碧图的原理与实例解释
  5. 中国企业海外征战路线图
  6. 强化学习 之 蒙特卡洛方法
  7. SpringCloud学习笔记-基本组件介绍
  8. 【无标题】item_search - 按关键字搜索淘宝商品API接口调用展示
  9. Word VBA:结合网友的自定义函数对汉字批量增 / 删拼音
  10. ESXI 6.0正式版官网下载地址