windows下C语言枚举串口端口

来源:互联网 发布:ios天气插件数据不跟新 编辑:程序博客网 时间:2024/05/22 03:23
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;
// 获取端口信息,能得到端口信息的大小 pcbNeededEnumPorts(NULL, 2, pBite, 0, &pcbNeeded, &pcReturned);pBite =(BYTE *)malloc(pcbNeeded);// 枚举端口,能得到端口的具体信息 pBite 以及端口的的个数 pcReturnedEnumPorts(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 包含进你的工程文件中就行了,该方法时间上来说可能和第三种方法差不多,但该方法获取的串口完完全全就是硬件设备管理器中的串口。
                                             
1 0
原创粉丝点击