window 如何枚举设备并禁用该设备和启用该设备?如何注册设备热拔插消息通知?...

目前实现的功能:
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

转载于:https://www.cnblogs.com/cheungxiongwei/p/10676051.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值