目前实现的功能:

1.设备枚举

2.设置设备禁用和启用

3.注册设备热拔插消息通知

4.获取设备 vid pid 数值

需要链接的库 SetupAPI.lib

DeviceManager 类如下:

DeviceManager.h

#include <string>
#include <vector> #include <setupapi.h>
#include <initguid.h>
#include <devguid.h> #include <stringapiset.h> #include <Dbt.h>
#include <Usbiodef.h> namespace zz { typedef struct tagDeviceInfo
{
//设备友好名称
std::wstring szFriendlyName;
//设备类
std::wstring szDeviceClass;
//设备描述
std::wstring szDeviceDesc;
//设备硬件ID
std::wstring szDeviceID;
//设备驱动
std::wstring szDriverName;
//设备实例
DWORD dwDevIns;
//设备类标志
GUID Guid; }DeviceInfo, *pDeviceInfo; // This GUID is for all USB serial host PnP drivers, but you can replace it
// with any valid device class guid.
static GUID WceusbshGUID = { 0x25dbce51, 0x6c8f, 0x4a72,0x8a,0x6d,0xb5,0x4c,0x2b,0x4f,0xc8,0x35 }; //GUID_DEVINTERFACE_USB_DEVICE class DeviceManager
{
public:
DeviceManager();
~DeviceManager();
//枚举设备
std::vector<DeviceInfo> enumDeviceInfo(bool isAllInfo = false);
//设置设备状态(禁用/停用),true 禁用,false 启用
bool setDeviceStatus(DeviceInfo &theDevice, bool bStatusFlag);
//pid
std::wstring vid(std::wstring deviceID);
//vid
std::wstring pid(std::wstring deviceID);
//注册设备热拔插通知 win8 以上可使用 CM_Register_Notification 函数 https://docs.microsoft.com/zh-cn/windows-hardware/drivers/install/registering-for-notification-of-device-interface-arrival-and-device-removal
BOOL DoRegisterDeviceInterfaceToHwnd(IN GUID InterfaceClassGuid, IN HWND hWnd, OUT HDEVNOTIFY *hDeviceNotify);
}; //utf8 编码
std::string utf8_encode(const std::wstring &wstr); }//zz

DeviceManager.cpp

#include "DeviceManager.h"

namespace zz {

	DeviceManager::DeviceManager()
{
} DeviceManager::~DeviceManager()
{
} std::vector<DeviceInfo> DeviceManager::enumDeviceInfo(bool isAllInfo)
{
//结果集
std::vector<DeviceInfo> result_set; HDEVINFO device_info_set;
//https://docs.microsoft.com/zh-cn/windows/desktop/api/setupapi/nf-setupapi-setupdigetclassdevsw
if (isAllInfo) {
//获取本地计算机所有设备信息集
device_info_set = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
}else {
//仅串口
device_info_set = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, NULL, NULL, DIGCF_PRESENT);
} if (device_info_set == INVALID_HANDLE_VALUE) {
fprintf(stderr, "GetLastError = %lu\r\n",GetLastError());
return result_set;
} SP_DEVINFO_DATA device_info_data;
SecureZeroMemory(&device_info_data, sizeof(SP_DEVINFO_DATA));
device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
unsigned long device_info_set_index = 0; //枚举设备
while (SetupDiEnumDeviceInfo(device_info_set, device_info_set_index, &device_info_data))
{
++device_info_set_index; TCHAR szFriendlyName[MAX_PATH] = { 0 };
TCHAR szDeviceClass[MAX_PATH] = { 0 };
TCHAR szDeviceDesc[MAX_PATH] = { 0 };
TCHAR szDeviceID[MAX_PATH] = { 0 };
TCHAR szDriverName[MAX_PATH] = { 0 }; //SPDRP_HARDWAREID //SPDRP_HARDWAREID
DeviceInfo device_info;
//获取友好名称
if (!SetupDiGetDeviceRegistryProperty(device_info_set, &device_info_data, SPDRP_FRIENDLYNAME, NULL, (PBYTE)szFriendlyName, MAX_PATH - 1, NULL)) {
fprintf(stderr, "%2d %s\r\n", device_info_set_index, utf8_encode(L"Get SPDRP_FRIENDLYNAME Failed").c_str());
} //获取设备类
if (!SetupDiGetDeviceRegistryProperty(device_info_set, &device_info_data, SPDRP_CLASS, NULL, (PBYTE)szDeviceClass, MAX_PATH - 1, NULL)) {
fprintf(stderr, "%2d %s\r\n", utf8_encode(L"Get SPDRP_CLASS Failed").c_str());
} //获取设备描述
if (!SetupDiGetDeviceRegistryProperty(device_info_set, &device_info_data, SPDRP_DEVICEDESC, NULL, (PBYTE)szDeviceDesc, MAX_PATH - 1, NULL)) {
fprintf(stderr, "%2d %s\r\n", device_info_set_index, utf8_encode(L"Get SPDRP_DEVICEDESC Failed").c_str());
} //获取驱动名称
if (!SetupDiGetDeviceRegistryProperty(device_info_set, &device_info_data, SPDRP_HARDWAREID, NULL, (PBYTE)szDeviceID, MAX_PATH - 1, NULL)) {
fprintf(stderr, "%2d %s\r\n", device_info_set_index, utf8_encode(L"Get SPDRP_HARDWAREID Failed").c_str());
} //获取驱动名称
if (!SetupDiGetDeviceRegistryProperty(device_info_set, &device_info_data, SPDRP_DRIVER, NULL, (PBYTE)szDriverName, MAX_PATH - 1, NULL)) {
fprintf(stderr, "%2d %s\r\n", device_info_set_index, utf8_encode(L"Get SPDRP_DRIVER Failed").c_str());
} device_info.szFriendlyName = szFriendlyName;
device_info.szDeviceClass = szDeviceClass;
device_info.szDeviceDesc = szDeviceDesc;
device_info.szDeviceID = szDeviceID;
device_info.szDriverName = szDriverName;
device_info.dwDevIns = device_info_data.DevInst;//实例
device_info.Guid = device_info_data.ClassGuid;//GUID result_set.push_back(device_info);
} if (device_info_set) {
SetupDiDestroyDeviceInfoList(device_info_set);
} return result_set;
} bool DeviceManager::setDeviceStatus(DeviceInfo & theDevice, bool bStatusFlag)
{
//获取设备信息集
HDEVINFO device_info_set = SetupDiGetClassDevs(&theDevice.Guid, 0, 0, DIGCF_PRESENT /*| DIGCF_ALLCLASSES */);
if (device_info_set == INVALID_HANDLE_VALUE) {
fprintf(stderr, "SetupDiGetClassDevs ERR!");
return false;
} SP_DEVINFO_DATA device_info_data;
SecureZeroMemory(&device_info_data, sizeof(SP_DEVINFO_DATA));
device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
unsigned long device_info_set_index = 0;
bool bFlag = false; //枚举设备判断指定的设备是否存在
while (SetupDiEnumDeviceInfo(device_info_set, device_info_set_index, &device_info_data)) {
++device_info_set_index;
if (theDevice.dwDevIns == device_info_data.DevInst) {
bFlag = true;
break;
}
} //
if (bFlag) { //https://docs.microsoft.com/en-us/windows/desktop/api/setupapi/ns-setupapi-_sp_propchange_params
SP_PROPCHANGE_PARAMS change;
change.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
change.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
change.Scope = DICS_FLAG_GLOBAL;
change.StateChange = bStatusFlag ? DICS_ENABLE : DICS_DISABLE;
change.HwProfile = 0; if (SetupDiSetClassInstallParams(device_info_set, &device_info_data, (SP_CLASSINSTALL_HEADER*)&change, sizeof(change))) {
if (!SetupDiChangeState(device_info_set, &device_info_data)) {
fprintf(stderr, "SetupDiChangeState ERR!");
bFlag = false;
}
}else {
fprintf(stderr, "SetupDiSetClassInstallParams ERR!");
bFlag = false;
}
}else {
fprintf(stderr, "Device not found!");
} //释放资源
SetupDiDestroyDeviceInfoList(device_info_set); return bFlag;
} std::wstring DeviceManager::vid(std::wstring deviceID)
{
auto pos = deviceID.rfind(L"vid_");
if (pos == std::wstring::npos) {
return std::wstring();
}
return deviceID.substr(pos + 4, 4);
} std::wstring DeviceManager::pid(std::wstring deviceID)
{
auto pos = deviceID.rfind(L"pid_");
if (pos == std::wstring::npos) {
return std::wstring();
}
return deviceID.substr(pos + 4, 4);
} // Routine Description:
// Registers an HWND for notification of changes in the device interfaces
// for the specified interface class GUID. // Parameters:
// InterfaceClassGuid - The interface class GUID for the device
// interfaces. // hWnd - Window handle to receive notifications. // hDeviceNotify - Receives the device notification handle. On failure,
// this value is NULL. // Return Value:
// If the function succeeds, the return value is TRUE.
// If the function fails, the return value is FALSE. // Note:
// RegisterDeviceNotification also allows a service handle be used,
// so a similar wrapper function to this one supporting that scenario
// could be made from this template. //窗口需要处理 WM_DEVICECHANGE 消息
//不需要时需要使用 BOOL UnregisterDeviceNotification(HDEVNOTIFY Handle); 函数关闭注册的设备通知
//https://docs.microsoft.com/zh-cn/windows/desktop/DevIO/wm-devicechange
BOOL DeviceManager::DoRegisterDeviceInterfaceToHwnd(IN GUID InterfaceClassGuid, IN HWND hWnd, OUT HDEVNOTIFY * hDeviceNotify)
{
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; SecureZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_classguid = InterfaceClassGuid; *hDeviceNotify = RegisterDeviceNotification(
hWnd, // events recipient
&NotificationFilter, // type of device
DEVICE_NOTIFY_WINDOW_HANDLE // type of recipient handle
); if (NULL == *hDeviceNotify)
{
fprintf(stderr, "RegisterDeviceNotification");
return FALSE;
} return TRUE;
} std::string utf8_encode(const std::wstring & wstr)
{ int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
std::string strTo(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
return strTo;
} }//zz

window 如何枚举设备并禁用该设备和启用该设备?如何注册设备热拔插消息通知?的更多相关文章

  1. 【转】iOS设备的UDID是什么?苹果为什么拒绝获取iOS设备UDID的应用?如何替代UDID?

    本文讲诉的主要是为什么苹果2011年8月发布iOS 5后就开始拒绝App获取设备的UDID以及UDID替补方案,特别提醒开发者苹果App Store禁止访问UDID的应用上架(相关推荐:APP被苹果A ...

  2. linux设备驱动归纳总结(八):2.总线、设备和驱动的关系【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-110295.html linux设备驱动归纳总结(八):2.总线.设备和驱动的关系 xxxxxxxxx ...

  3. linux设备驱动归纳总结(八):1.总线、设备和驱动【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-109733.html linux设备驱动归纳总结(八):1.总线.设备和驱动 xxxxxxxxxxxx ...

  4. linux设备驱动归纳总结(三):2.字符型设备的操作open、close、read、write【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-59417.html linux设备驱动归纳总结(三):2.字符型设备的操作open.close.rea ...

  5. linux设备驱动归纳总结(三):1.字符型设备之设备申请【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-59416.html linux设备驱动归纳总结(三):1.字符型设备之设备申请 操作系统:Ubunru ...

  6. linux driver ------ platform模型,通过杂项设备(主设备号是10)注册设备节点

    注册完设备和驱动之后,就需要注册设备节点 Linux杂项设备出现的意义在于:有很多简单的外围字符设备,它们功能相对简单,一个设备占用一个主设备号对于内核资源来说太浪费.所以对于这些简单的字符设备它们共 ...

  7. [Apple开发者帐户帮助]七、注册设备(1)注册一个设备

    您需要已注册的设备来创建开发或临时配置文件.要使用开发人员帐户注册设备,您需要拥有设备名称和设备ID. 注意:如果您使用自动签名,Xcode会为您注册连接的设备.Xcode Server也可以配置为注 ...

  8. 【Linux开发】linux设备驱动归纳总结(八):2.总线、设备和驱动的关系

    linux设备驱动归纳总结(八):2.总线.设备和驱动的关系 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  9. 【Linux开发】linux设备驱动归纳总结(八):1.总线、设备和驱动

    linux设备驱动归纳总结(八):1.总线.设备和驱动 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

随机推荐

  1. QT 中设置按钮图片和文字的两种方法

    1.使用QpushButton自带的API实现: void setIcon(const QIcon &icon) void setText(const QString &text) 该 ...

  2. TortoiseGit状态图标不能显示

    一开始网上搜到的办法基本都一样,都试过了,没有效果: 办法一: 注册表中找到 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\ ...

  3. python学习笔记(8)--爬虫下载占位图片

    说明: 1. 虽然很简单,但总忘,所以还是记下来吧! 2. http://placekitten.com/300/300这个画猫的网站老是打开没有图片,改成了http://placehold.it/3 ...

  4. JS学习笔记(2)--正则表达式获取指定字符串

    js 正则提取字串 这里就有:SA 怎么用正则提取sa出来 var str=“这里就有:SA ”怎么用正则提取sa出来 YDhcui | 浏览 2087 次 推荐于2016-05-30 18:25:4 ...

  5. java 解压.gz文件

    1.//建立gzip压缩文件输入流 2.建立gzip解压工作流 fileInputStream = new FileInputStream(filePath + fileName); //解凍する G ...

  6. 清除Css中select的下拉箭头样式

    select {/*Chrome和Firefox里面的边框是不一样的,所以复写了一下*/border: solid 1px #000; /*很关键:将默认的select选择框样式清除*/appeara ...

  7. kettle两表内链接的查询结果与sql语句的查询结果不符合?

    1.教师表输入 2.学生表 查 3.学生表中查出的教师id进行排序 5.教师表中查出的同样也对教师的id进行排序 6.进行左连接 总结: 进行连接的时候的关键是同样对教师的id进行先排序

  8. pycharm Tab键设置成4个空格

    file--->setting,选择Editor--->python,如下图所示:

  9. imx lcd HV和DE模式转换

    有些时候拿到的lcd手册中关于芯片的时序使用的DE模式的,而imx6内核中使用的参数设置趋势HV模式,应此就需要将DE模式的参数转化为HV模式. 参考链接: https://community.nxp ...

  10. jquery -- 触屏设备touch事件

    几种普及得比较好的触摸事件,你可以在绝大多数现代浏览器中来测试这一事件(必须是触屏设备哦): touchstart:触摸开始的时候触发 touchmove:手指在屏幕上滑动的时候触发 touchend ...