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

400次阅读

在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);
}
yiywain
版权声明:本文于2022-01-17转载自VC/MFC根据USB设备PID、VID自动查找串口号,共计3226字。
转载提示:此文章非本站原创文章,若需转载请联系原作者获得转载授权。