windows下C语言枚举串口端口

本文介绍了四种不同的方法来枚举计算机上的串行端口(COM口),包括使用注册表、EnumPort方法、逐个尝试打开及使用SetupAPI函数集。每种方法都有其优缺点,如实时性、可靠性等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.用注册表
	HKEY hKEY;
	LPCTSTR data_Set="HARDWARE\\DEVICEMAP\\SERIALCOMM"; 
	long i;
	int j=0;
	SFC_BYTE Data_Get[10]={0};
	TCHAR szValueName[255];
	DWORD dwValueName = sizeof(szValueName);
	LPDWORD lpType = 0;
	DWORD cbData = 255;
	SFC_INT Port_Num=0;
	SFC_BYTE strPort[20][5]={0};
	{
		return -1;
		
	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,data_Set, 0, KEY_READ, &hKEY))    //打开注册表
	for (i=0;i<20;i++) //   缺点:必须要有确定的i值
	{
		memset(Data_Get,0,10);
		(RegEnumValue(hKEY,i,szValueName,&dwValueName,NULL,lpType,Data_Get,&cbData));
		if (Data_Get[0]!=0)
		{
			memcpy(strPort[j],Data_Get,sizeof(Data_Get));
			Port_Num += 1;
			j++;
		}
	}
	RegCloseKey(hKEY);    //关闭注册表
	
	如果用户在装某些软硬件时在注册表中注册了虚拟串口之类的,用此法枚举得到的该类串口实际上是不能当串口用的。并且此法基本上不可能枚举出来虚拟的串口。

2.使用 EnumPort 方法
	//枚举端口
	long i;
	int j=0;
SFC_INT Port_Num=0;
SFC_BYTE strPort[20][5]={0};
LPBYTE pBite  = NULL;
DWORD pcbNeeded = 0;  // bytes received or required
DWORD pcReturned = 0;  // number of ports received
PORT_INFO_2 *pPort;
	// 获取端口信息,能得到端口信息的大小 pcbNeeded

	EnumPorts(NULL, 2, pBite, 0, &pcbNeeded, &pcReturned);
	pBite =(BYTE *)malloc(pcbNeeded);

	// 枚举端口,能得到端口的具体信息 pBite 以及端口的的个数 pcReturned

	EnumPorts(NULL, 2, pBite, pcbNeeded, &pcbNeeded, &pcReturned);
	pPort = (PORT_INFO_2*)pBite;
	for ( i = 0; i < pcReturned; i++)
	{
		if (strstr(pPort[i].pPortName,"COM"))
		{
			memcpy(strPort[j],pPort[i].pPortName,sizeof(pPort[i].pPortName));
			Port_Num++;
			j++;
		}
	}
		以上方法除了串口,还可以枚举所有的并口和打印机等接口,并且耗时较短,而且能找到虚拟串口(这些串口有些未使用时,在注册表和硬件设备管理器中是不能取得的)。
		但是使用这种方法有一个问题,就是不能实时更新枚举的端口。例如,我现在有一个 COM5 通过Enumport 函数可以枚举出来,然后我将该COM口改为从来没有用过的COM7,再枚举的话就不会枚举到COM7,依然只会枚举到COM5,必须重新启动计算机后,再来枚举的话,才会枚举到COM7。 所以这种方法并不适用于需要经常修改COM口的设备程序使用。

3.使用最笨的一个一个打开的办法
	int m_nSerialPortNum;// 串口计数
	CString  strSerialList[56];  // 临时定义 256 个字符串组
	CString  m_nSerialPortNo[56];
	m_nSerialPortNum=0;// 串口计数
	CString temp;
	HANDLE hCom;
	for (int i=1;i<=32;i++)
	{
		if (i<10)
		{
			temp.Format(_T("COM%d"),i);
			hCom = CreateFile(temp, 0, 0, 0,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
			if(INVALID_HANDLE_VALUE == hCom )
				continue;
			strSerialList[m_nSerialPortNum] = temp;
			m_nSerialPortNo[m_nSerialPortNum]=temp.Right(temp.GetLength()-3);
			m_nSerialPortNum++;         
			CloseHandle(hCom);
		}
		if (i>=10)
		{
			temp.Format(_T("\\\\.\\COM%d"),i);
			hCom = CreateFile(temp, 0, 0, 0,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
			if(INVALID_HANDLE_VALUE == hCom )
				continue;
			strSerialList[m_nSerialPortNum] = temp.Right(temp.GetLength()-4);
			m_nSerialPortNo[m_nSerialPortNum]=temp.Right(temp.GetLength()-7);
			m_nSerialPortNum++;         
			CloseHandle(hCom);
		}
		
	
		
	for (int i=0;i<m_nSerialPortNum;i++)
	{
		m_serialportnumtp.AddString(LPCTSTR(strSerialList[i]));
	}

	这个笨办法虽然耗时,但是相当的可靠,只要是设备管理器能显示出来的基本都可以找到,就算你虚拟出来很多虚拟的串口,设备管理器里显示不出来,它照样可以找到。  不过缺点也很明显,循环的话必须要有固定的值,你必须确定COM口的数量,所以动态扩展性较差。

4 、使用 SetupAPI 函数集的方法

此种方法是最简单并且有效的方法,之所以简单是因为已经有人将复杂的代码封装起来了,我只需像傻子一样调用就可以完成工作了,具体的说明请看
http://www.codeguru.com/Cpp/W-P/system/hardwareinformation/article.php/c5721/ ,下面给出本人调用该方法的例子代码:

       int m_nSerialPortNum(0);// 串口计数
       CString          strSerialList[256];  // 临时定义 256 个字符串组
       CArray<SSerInfo,SSerInfo&> asi;
       EnumSerialPorts(asi,TRUE);// 参数为 TRUE 时枚举当前可以打开的串口,
// 否则枚举所有串口
       m_nSerialPortNum = asi.GetSize();
       for (int i=0; i<asi.GetSize(); i++)
       {
              CString str = asi[i].strFrien dlyName;
       }
补充说明一下,使用该方法只要在你的程序中,添加“ EnumSerial.cpp ”和“ EnumSerial.h ”两个文件,并且将 Setupapi.lib 包含进你的工程文件中就行了,该方法时间上来说可能和第三种方法差不多,但该方法获取的串口完完全全就是硬件设备管理器中的串口。



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值