目前实现的功能:

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. java:常用的两种设计模式(单例模式和工厂模式)

    一.单例模式:即一个类由始至终只有一个实例.有两种实现方式(1)定义一个类,它的构造方法是私有的,有一个私有的静态的该类的变量在初始化的时候就实例化,通过一个公有的静态的方法获取该对象.Java代码  ...

  2. PHP——连接数据库初

    <?php //1.生成连接 造连接对象 //$db=new mysqli($dbhost(服务器),$username,$userpass,$dbdatabase); $db = new my ...

  3. 亿级Web系统的容错性建设实践(转)

    三年多前,我在腾讯负责的活动运营系统,因为业务流量规模的数倍增长,系统出现了各种各样的异常,那个时候,我7*24小时地没日没夜处理告警,周末和凌晨也经常上线,疲于奔命.后来,当时的老领导对我说:你不能 ...

  4. 如何解决redis高并发客户端频繁time out?

    解决方案:https://www.zhihu.com/question/24781521

  5. json datatable互转(真正能用的-原创)

    网上有不少的转换类 可是不全 或者有错误 我现在贴一个 js 和C# 互转代码 希望能帮到需要的童鞋 首先C#转成 json /// <summary>         /// DataT ...

  6. Linux 高频工具快速教程

    全书分为三个部分: 第一部分为基础篇,介绍我们工作中常用的工具的高频用法: 第二部分为进阶篇,介绍的工具更多的适合程序员使用,分为程序构建.程序调试及程序优化: 第三部分是工具参考篇,主要介绍实用工具 ...

  7. 点击edittext并显示其内容

    package com.example.sum;//sum import com.example.sum.R;//sum import android.app.Activity; import and ...

  8. ubuntu 安装dlib 出现dlib.so: undefined symbol: png_set_longjmp_fn

    参考网上的教程安装dlib 安装教程1 sudo apt-get install libboost-python-dev cmake sudo pip install dlib 安装教程2ubuntu ...

  9. 【BZOJ】1641: [Usaco2007 Nov]Cow Hurdles 奶牛跨栏(floyd)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1641 这种水题无意义... #include <cstdio> #include < ...

  10. sed替换

    1. sed可以替换给定的文本中的字符串,可以利用正则表达式进行匹配$ sed 's/pattern/replace_string/' file或者$ cat file | sed 's/patter ...