zoukankan      html  css  js  c++  java
  • 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
    ",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
    ", 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
    ", 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
    ", 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
    ", 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
    ", 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
    
  • 相关阅读:
    P1144 最短路计数 题解 最短路应用题
    C++高精度加减乘除模板
    HDU3746 Teacher YYF 题解 KMP算法
    POJ3080 Blue Jeans 题解 KMP算法
    POJ2185 Milking Grid 题解 KMP算法
    POJ2752 Seek the Name, Seek the Fame 题解 KMP算法
    POJ2406 Power Strings 题解 KMP算法
    HDU2087 剪花布条 题解 KMP算法
    eclipse创建maven项目(详细)
    maven的作用及优势
  • 原文地址:https://www.cnblogs.com/cheungxiongwei/p/10676051.html
Copyright © 2011-2022 走看看