VC/MFC根据USB设备PID、VID自动查找串口号

在VC/MFC环境下有两种方法来根据PID、VID获取对应的串口号,这样操作的目的是避免客户手动设定下拉框的信息,让软件自动识别!当然,前提是有自己的USB PID、VID


下面是C++代码示例:


// 第一种方法需要包含此头文件
#include <SetupAPI.h>
#pragma comment(lib, "Setupapi.lib")

#define MY_USB_PID_VID	_T("VID_1111&PID_2222")

/************************************************************************/
/* 根据USB描述信息字符串中读取
/************************************************************************/
int MTGetPortFromVidPid(CString strVidPid)
{
	// 获取当前系统所有使用的设备
	int					nPort	= -1;
	int					nStart	= -1;
	int					nEnd	= -1;
	int					i		= 0;
	CString				strTemp, strName;
	DWORD				dwFlag = (DIGCF_ALLCLASSES | DIGCF_PRESENT);
	HDEVINFO			hDevInfo = INVALID_HANDLE_VALUE;
	SP_DEVINFO_DATA		sDevInfoData;
	TCHAR				szDis[MAX_PATH] = {0x00};// 存储设备实例ID
	TCHAR				szFN[MAX_PATH]  = {0x00};// 存储设备实例属性
	DWORD				nSize = 0 ;

	// 准备遍历所有设备查找USB
	hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, dwFlag);
	if( INVALID_HANDLE_VALUE == hDevInfo )
		goto STEP_END;

	// 开始遍历所有设备
	memset(&sDevInfoData, 0x00, sizeof(SP_DEVICE_INTERFACE_DATA));
	sDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	for(i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &sDevInfoData); i++ )
	{
		nSize = 0;
		
		// 无效设备
		if ( !SetupDiGetDeviceInstanceId(hDevInfo, &sDevInfoData, szDis, sizeof(szDis), &nSize) )			
			goto STEP_END;

		// 根据设备信息寻找VID PID一致的设备
		strTemp.Format(_T("%s"),szDis);
		strTemp.MakeUpper();
		if ( strTemp.Find(strVidPid, 0) == -1 )
			continue;

		// 查找设备属性
		nSize = 0;
		SetupDiGetDeviceRegistryProperty(hDevInfo, &sDevInfoData,
			SPDRP_FRIENDLYNAME,
			0, (PBYTE) szFN,
			sizeof(szFN),
			&nSize);

		// "XXX Virtual Com Port (COM7)"
		strName.Format(_T("%s"),szFN);
		if(strName.IsEmpty())
			goto STEP_END;

		// 寻找串口信息
		nStart = strName.Find(_T("(COM"), 0);
		nEnd = strName.Find(_T(")"), 0);
		if(nStart == -1 || nEnd == -1)
			goto STEP_END;

		strTemp = strName.Mid(nStart + 4, nEnd - nStart - 2);
		nPort = atoi(strTemp);
	}

STEP_END:
	// 关闭设备信息集句柄
	if(hDevInfo != INVALID_HANDLE_VALUE)
	{
		SetupDiDestroyDeviceInfoList(hDevInfo);
		hDevInfo = INVALID_HANDLE_VALUE;
	}

	return nPort;
}


/************************************************************************/
/* 根据注册表中的PID、VID信息读取
/************************************************************************/
int MTUpdateSerialPort(CString strVidPid)
{
	DWORD	dwIndex = 0;
	HKEY	hKey;
	TCHAR	CommName[_MAX_FNAME] = {0x00};
	DWORD	lcbName = _MAX_FNAME;
	DWORD	lValue = MAX_PATH;
	TCHAR	szValue[MAX_PATH];
	LONG	lRtn = 0;
	CString	strTemp, strKey;
	int		nPort	= -1;
	int		nStart	= -1;
	int		nEnd	= -1;
	
	// 读取PID对应的端口
	strTemp.Format_T("SYSTEM\\CurrentControlSet\\Enum\\USB\\%s"),strVidPid);
	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, strTemp, NULL, KEY_READ, &hKey) == ERROR_SUCCESS) 
	{
		dwIndex = 0;
		while (RegEnumKey(hKey,dwIndex++,CommName,lcbName) == ERROR_SUCCESS) 
		{
			// 读取PID对应的端口
			strKey.Format(_T("SYSTEM\\CurrentControlSet\\Enum\\USB\\%s\\%s\\Device Parameters"),strVidPid,CommName);
			RegCloseKey(hKey);
			if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,strKey,NULL,KEY_READ,&hKey) == ERROR_SUCCESS) 
			{
				lRtn = RegQueryValueEx(hKey,_T("PortName"),NULL,&lValue,(LPBYTE)szValue,&lValue);
				if ( lRtn == ERROR_SUCCESS) 
				{
					// 寻找串口信息
					strName.Format(_T("%s"),szValue);
					nStart = strName.Find(_T("COM"), 0);
					nEnd = strName.Find(_T(")"), 0);
					if(nStart == -1 || nEnd == -1)
					{
						RegCloseKey(hKey);
						return -1;
					}

					strTemp = strName.Mid(nStart + 3, nEnd - nStart);
					nPort = atoi(strTemp);

					RegCloseKey(hKey);
					return nPort;
				}
			}

			lValue  = MAX_PATH;
			lcbName = MAX_PATH;
		}

		RegCloseKey(hKey);
	}

	return nPort;
}

void main()
{
	int		nPort = -1;
	
	// 第一种方法遍历USB设备描述
	nPort = MTGetPortFromVidPid(MY_USB_PID_VID);
	
	// 第二种方法遍历注册表的PID、VID属性
	nPort = MTUpdateSerialPort(MY_USB_PID_VID);
	if(nPort == -1)
		printf("未找到 %s 相关串口号!\n");
	else
		printf("成功找到串口号:COM%d \n",nPort);
}


猜你喜欢

转载自blog.csdn.net/wangningyu/article/details/78696221