在VC/MFC环境下有两种方法来根据PID、VID获取对应的串口号,这样操作的目的是避免客户手动设定下拉框的信息,让软件自动识别!当然,前提是有自己的USB PID、VID;
注:USB转的串口才有PID和VID,USB转的串口的串口号会变,可以通过PID和VID反找串口号,进行串口连接。机器原生的串口,串口号是固定的,没有PID和VID,更不需要用这种方法去找串口号。
转载自代码先锋网:VC/MFC根据USB设备PID、VID自动查找串口号
// 第一种方法需要包含此头文件
#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);
}