目前实现的功能:

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. python3+spark2.1+kafka0.8+sparkStreaming

    python代码: import time from pyspark import SparkContext from pyspark.streaming import StreamingContex ...

  2. 【pywin32总结】

    #下面是必备的#注意!所有方法后面都要加括号()!!! import win32com from win32com.client import Dispatch,constants w = win32 ...

  3. c#用picturebox显示多页TIF

    //引用 using System.Drawing; using System.Drawing.Imaging; //以下是方法 private Bitmap myImage = null; priv ...

  4. CSS(二):选择器

    一.基本选择器 1.标签选择器 HTML标签作为标签选择器的名称,例如<h1>~<h6>.<p>等. 语法: p{font-size: 16px;} p:标签选择器 ...

  5. MongoDB助力快速搭建物流订单系统

    简介 快递物流系统里最常见的一种业务类型就是订单的查询和记录.订单的特点是随着递送过程,订单数据需要随时更新路径.数据结构上需要可以灵活应对,这点非常符合Document模型,并且MongoDB支持G ...

  6. 【转】VC调试的时候 “没有调试信息,未加载符号”

    概述调试是一个程序员最基本的技能,其重要性甚至超过学习一门语言.不会调试的程序员就意味着他即使会一门语言,却不能编制出任何好的软件.这里我简要的根据自己的经验列出调试中比较常用的技巧,希望对大家有用. ...

  7. 织梦dede模板中广告的去除方法?

    织梦)dede模板中广告的去除方法1.我们先删除头部的广告,找到templetsdefault下的head.htm文件,打开后找到<div>{dede:myad name=’innerTo ...

  8. ActionContextCleanUp

    ActionContextCleanUp作用   延长action中属性的生命周期,包括自定义属性,以便在jsp页面中进行访问,让actionContextcleanup过滤器来清除属性,不让acti ...

  9. (转)FS_S5PC100平台上Linux Camera驱动开发详解(一) .

     平台linuxstructlinux内核videocam 说明:        理解摄像头驱动需要四个前提:        1)摄像头基本的工作原理和S5PC100集成的Camera控制器的工作原理 ...

  10. (转)c指针问题

    字符串常量问题: http://blog.csdn.net/zhongyili_sohu/article/details/8084188 1. 常量字符串 在代码里直接出现的”abcdef”这种字符串 ...