本文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表示只返回当前系统中存在的(已连接)设备。);AI写代码
该函数的第一个入口参数GUID指定了我们想要检索什么类型的设备,它的取值可以在devguid文件中查找,这里不一一列举。本例中会只用到以下GUID,它们的含义如下:
GUID_DEVCLASS_SYSTEM // 系统设备GUIDGUID_DEVCLASS_USB // USB设备GUIDGUID_DEVCLASS_MOUSE // 鼠标设备GUIDGUID_DEVCLASS_NET // 网络设备GUIDGUID_DEVCLASS_KEYBOARD // 键盘设备GUIDAI写代码
当调用完此函数并处理完相应数据后,必须调用SetupDiDestroyDeviceInfoList函数,否则内存溢出。
3.1.2.SetupDiEnumDeviceInfo
SetupDiEnumDeviceInfo函数返回一个SP_DEVINFO_DATA结构,它指定该设备的信息集的设备的信息元素。
BOOLSetupDiEnumDeviceInfo( _In_ HDEVINFO DeviceInfoSet, // 设备信息集的句柄,即SetupDiGetClassDevs返回的句柄 _In_ DWORD MemberIndex, // 要检索的设备信息元素的从零开始的索引 _Out_ PSP_DEVINFO_DATA DeviceInfoData // 指向SP_DEVINFO_DATA结构的指针,以接收有关枚举设备信息元素的信息 );AI写代码
3.1.3.SetupDiGetDeviceRegistryProperty
SetupDiGetDeviceRegistryProperty检索指定的即插即用设备属性.
BOOLSetupDiGetDeviceRegistryPropertyW( _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缓冲区的大小(单位:字节) );AI写代码
该函数的第三个入口参数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)AI写代码
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)));AI写代码
其中:
ui.treeView:即UI上的QTreeView控件
SIGNAL:信号,当设备树上某个节点被鼠标点击时,会自动emit信号
SLOT:槽函数,Jungle自己定义实现的处理函数,根据QModelIndex获取父节点和该节点索引
3.2.2.QTimer
定时器,定时刷新设备树。计算机上连接的设备可能会动态改变,比如插拔USB设备。关于QTimer的使用在此也不详述。本例中有以下信号槽连接:
connect(timer, SIGNAL(timeout()), this, SLOT(refreshTree()));AI写代码
其中,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};AI写代码
4.3.LOG
这是Jungle自行设计实现的一个日志系统,方便调试跟踪程序运行状况,设计语言为C++。这部分内容可以参见Jungle的博客:C++设计实现日志系统。
5.实现
5.1.UsbQtViewer
头文件:
class UsbViewerQt : public QMainWindow{ Q_OBJECT public: UsbViewerQt(QWidget *parent = 0); ~UsbViewerQt(); // Init treeModel void initTreeModel(); // Refresh the device list void refreshDeviceList(DeviceClass deviceClass, QStandardItem* deviceTreeRoot); // Retrieve the host name QString getHostName(); // timer QTimer* timer; public slots: // slots: when the tree is clicked void getTreeClicked(const QModelIndex index); // slots: refresh tree when timer timeout void refreshTree(); private: Ui::UsbViewerQtClass ui; QTreeView* pTreeView; // UI tree root model QStandardItemModel* rootModel; // Usb device info list QStringList usbInfoList; // System device info list QStringList systemInfoList; // Mouse device info list QStringList mouseInfoList; // Net device info list QStringList netInfoList; // Keyboard device info list QStringList keyBoardInfoList; // Logger LOG* Log;};AI写代码
源文件:
#include "UsbViewerQt.h" #include <QtNetwork\qhostinfo.h> UsbViewerQt::UsbViewerQt(QWidget *parent) : QMainWindow(parent){ ui.setupUi(this); setWindowIcon(QIcon("Icon/Token.png")); rootModel = NULL; // Log Log = LOG::getInstance(); // Init tree view initTreeModel(); // Timer this->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 Tree if (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 info char 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 item QString objectName = ui.treeView->model()->itemData(iIndex).values()[0].toString(); // 2. Get the father item to distinguish the device class QStandardItem* 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 name int index = 0; for (index; index < deviceInfoList.size(); index++){ if (deviceInfoList[index] == objectName){ break; } } // 4. Retrieve the device detailed info with the index char 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();}AI写代码
5.2.UsbInterface
头文件:
#ifndef _USBINTERFACE_H_#define _USBINTERFACE_H_ #define INDEX_ALL -1 enum 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_AI写代码
源文件:
#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 computer hDevInfo = SetupDiGetClassDevs( &guid, 0, 0, DIGCF_PRESENT ); if (hDevInfo == INVALID_HANDLE_VALUE) { res = GetLastError(); return res; } // enumerute device information DWORD required_size = 0; // SetupDiEnumDeviceInfo: returns a SP_DEVINFO_DATA structure that specifies a device information element in a device information set if (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 property if (!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 DESCRIPTION LOG_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 HARDWAREID LOG_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 COMPATIBLEIDS LOG_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 SERVICE LOG_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 CLASS LOG_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 CLASSGUID LOG_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 DRIVER LOG_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 MFG LOG_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_INFORMATION LOG_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_DATA LOG_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 FRIENDLYNAME LOG_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_PATHS LOG_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;}AI写代码
5.3.LOG
该部分略,详见Github或者C++设计实现日志系统
6.效果
在工程路径的Log文件夹下可以看到日志文件UsbViewerQt.log:
共同學習,寫下你的評論
評論加載中...
作者其他優質文章