博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Methods Collection of Enumerating Com Port in Windows, by C
阅读量:5864 次
发布时间:2019-06-19

本文共 8915 字,大约阅读时间需要 29 分钟。

     According to this , PJ Naughter has implemented 9 methods to emunerate com port in Windows. That code was named .
     As my using, I found some method would list non-existed com ports. for example:
My computer com port be :
 But the output of  PJ Naughte's EnumSerialPorts be :
CreateFile method reportsCOM1COM4COM5COM98COM99QueryDosDevice method reportsCOM5COM1COM98COM99COM4GetDefaultCommConfig method reportsCOM1COM4COM5COM98COM99Device Manager (SetupAPI - GUID_DEVINTERFACE_COMPORT) reportsCOM1 
<通訊連接埠>
COM4
Device Manager (SetupAPI - Ports Device information set) reportsCOM99
COM4
COM1
<通訊連接埠>
COM98
COM5
EnumPorts method reportsCOM1COM2COM4COM7COM8COM10COM6COM5COM98COM99COM9COM11COM12COM13COM14COM16COM17COM18COM19COM20COM21COM22COM23COM24COM25COM26COM27COM28COM29COM30COM31COM32COM3WMI method reportsCOM1
<通訊連接埠 (com1)>
ComDB method reportsCOM1COM3COM4COM5COM6COM7COM8COM9COM22COM23COM24COM25COM26COM27COM28COM29COM30COM31COM32COM98COM99Registry method reportsCOM98COM99COM5COM1COM4
    Otherwise, that code are too extrvagen, those is hard to separate into an individual function: it is too much dependency on the other functions.
I has reorganized those functions being independent forms in C(instead of C++), those are more portable and useful. I also eliminated some methods which would report unused com ports.
My code be :
/* Enumerating com ports in Windows  original by PJ Naughter, 1998 - 2013  http://www.naughter.com/enumser.html  (Web: www.naughter.com, Email: pjna@naughter.com) reorganize by Gaiger Chen , Jul, 2015 NO COPYRIGHT,  welcome to use for everyone.*/#include 
#include
#include
#include
#include
#define MAX_PORT_NUM (256)#define MAX_STR_LEN (256*sizeof(TCHAR))/*assure portName be double ARRAY , not double point*/BOOL EnumerateComPortByCreateFile(UINT *pNumber, TCHAR *pPortName, int strMaxLen){
UINT i, jj; INT ret; TCHAR *pTempPortName; *pNumber = 0; jj = 0; pTempPortName = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, strMaxLen*sizeof(pTempPortName)); ret = FALSE; for (i = 1; i<= 255; i++){
HANDLE hSerial; _stprintf_s(pTempPortName, strMaxLen, TEXT("\\\\.\\COM%u"), i); hSerial = CreateFile(pTempPortName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if(INVALID_HANDLE_VALUE == hSerial) continue; _tcsncpy(pPortName + jj*strMaxLen, pTempPortName, _tcsnlen(pTempPortName, strMaxLen)); jj++; }/*for [i MAX_PORT_NUM] */ HeapFree(GetProcessHeap(), 0, pTempPortName); pTempPortName = NULL; *pNumber = jj; if(0
= dwAllocatedSize) continue; //NULL terminate the data if it was not returned NULL terminated because it is not stored null terminated in the registry if (pszPortName[dwReturnedSize/sizeof(TCHAR) - 1] != _T('\0')) pszPortName[dwReturnedSize/sizeof(TCHAR)] = _T('\0'); }/*local varable*/ //If it looks like "COMX" then //add it to the array which will be returned nLen = _tcslen(pszPortName); if (3 < nLen) { if (0 == _tcsnicmp(pszPortName, TEXT("COM"), 3)) { if(FALSE == isdigit(pszPortName[3]) ) continue; //Work out the port number _tcsncpy(pPortName + jj*strMaxLen, pszPortName, _tcsnlen(pszPortName, strMaxLen)); //_stprintf_s(&portName[jj][0], strMaxLen, TEXT("%s"), pszPortName); } else { continue; }/*if 0 == _tcsnicmp(pszPortName, TEXT("COM"), 3)*/ }/*if 3 < nLen*/ LocalFree(pszPortName); isFound = TRUE; //Close the key now that we are finished with it RegCloseKey(hDeviceKey); }/*INVALID_HANDLE_VALUE != hDeviceKey*/ if(FALSE == isFound) continue; //If the port was a serial port, then also try to get its friendly name { TCHAR szFriendlyName[1024]; DWORD dwSize; DWORD dwType; szFriendlyName[0] = _T('\0'); dwSize = sizeof(szFriendlyName); dwType = 0; if( (TRUE == SetupDiGetDeviceRegistryPropertyFunPtr(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, (PBYTE)(szFriendlyName), dwSize, &dwSize) ) && (REG_SZ == dwType) ) { _tcsncpy(pFriendName + jj*strMaxLen, &szFriendlyName[0], _tcsnlen(&szFriendlyName[0], strMaxLen)); } else { _stprintf_s(pFriendName + jj*strMaxLen, strMaxLen, TEXT("")); }/*if SetupDiGetDeviceRegistryPropertyFunPtr */ }/*local variable */ jj++; }while(1); *pNumber = jj; if(0
= dwAllocatedSize) continue; //NULL terminate the data if it was not returned NULL terminated because it is not stored null terminated in the registry if (pszPortName[dwReturnedSize/sizeof(TCHAR) - 1] != _T('\0')) pszPortName[dwReturnedSize/sizeof(TCHAR)] = _T('\0'); }/*local varable*/ //If it looks like "COMX" then //add it to the array which will be returned nLen = _tcslen(pszPortName); if (3 < nLen) { if (0 == _tcsnicmp(pszPortName, TEXT("COM"), 3)) { if(FALSE == isdigit(pszPortName[3]) ) continue; //Work out the port number _tcsncpy(pPortName + jj*strMaxLen, pszPortName, _tcsnlen(pszPortName, strMaxLen)); //_stprintf_s(&portName[jj][0], strMaxLen, TEXT("%s"), pszPortName); } else { continue; }/*if 0 == _tcsnicmp(pszPortName, TEXT("COM"), 3)*/ }/*if 3 < nLen*/ LocalFree(pszPortName); isFound = TRUE; //Close the key now that we are finished with it RegCloseKey(hDeviceKey); }/*INVALID_HANDLE_VALUE != hDeviceKey*/ if(FALSE == isFound) continue; //If the port was a serial port, then also try to get its friendly name { TCHAR szFriendlyName[1024]; DWORD dwSize; DWORD dwType; szFriendlyName[0] = _T('\0'); dwSize = sizeof(szFriendlyName); dwType = 0; if( (TRUE == SetupDiGetDeviceRegistryPropertyFunPtr(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, (PBYTE)(szFriendlyName), dwSize, &dwSize) ) && (REG_SZ == dwType) ) { _tcsncpy(pFriendName + jj*strMaxLen, &szFriendlyName[0], _tcsnlen(&szFriendlyName[0], strMaxLen)); } else { _stprintf_s(pFriendName + jj*strMaxLen, strMaxLen, TEXT("")); }/*if SetupDiGetDeviceRegistryPropertyFunPtr */ }/*local variable */ jj++; }while(1); HeapFree(GetProcessHeap(), 0, pGuid); *pNumber = jj; if(0
\n"), &portName[i][0], &friendlyName[i][0]); setlocale(LC_CTYPE, nativeLocale); for(i = 0; i< MAX_PORT_NUM; i++){ ZeroMemory(&portName[i][0], MAX_STR_LEN); ZeroMemory(&friendlyName[i][0], MAX_STR_LEN); }/*for i[i MAX_PORT_NUM]*/ _tprintf(TEXT("\nSetupAPI SetupDiClassGuidsFromNamePort method : \n")); TIMER_BEGIN(EnumerateComPortSetupAPISetupDiClassGuidsFromNamePort); EnumerateComPortSetupAPISetupDiClassGuidsFromNamePort(&n, &portName[0][0], MAX_STR_LEN, &friendlyName[0][0]);TIMER_END(EnumerateComPortSetupAPISetupDiClassGuidsFromNamePort); _tprintf(TEXT("sought %d:\n"), n); setlocale(LC_CTYPE, "" ); for(i = 0; i< n; i++) _tprintf(TEXT("\t%s <%s> \n"), &portName[i][0], &friendlyName[i][0]); setlocale(LC_CTYPE, nativeLocale); for(i = 0; i< MAX_PORT_NUM; i++) ZeroMemory(&portName[i][0], MAX_STR_LEN); _tprintf(TEXT("\nRegistry method : \n"));TIMER_BEGIN(EnumerateComPortRegistry); EnumerateComPortRegistry(&n, &portName[0][0], MAX_STR_LEN);TIMER_END(EnumerateComPortRegistry); _tprintf(TEXT("sought %d:\n"), n); for(i = 0; i< n; i++) _tprintf(TEXT("\t%s\n"), &portName[i][0]); return 0; }/*main*/
The output be :
CreateFile method :EnumerateComPortByCreateFile cost time = 35 mssought 5:        \\.\COM1        \\.\COM4        \\.\COM5        \\.\COM98        \\.\COM99QueryDosDevice method : EnumerateComPortQueryDosDevice cost time = 7 mssought 5:        COM5        COM1        COM98        COM99        COM4GetDefaultCommConfig method :EnumerateComPortByGetDefaultCommConfig cost time = 772 mssought 5:        COM1        COM4        COM5        COM98        COM99SetupAPI GUID_DEVINTERFACE_COMPORT method :EnumerateComPortSetupAPI_GUID_DEVINTERFACE_COMPORT cost time = 12 mssought 2:        COM1 
<通訊連接埠>
COM4
SetupAPI SetupDiClassGuidsFromNamePort method :EnumerateComPortSetupAPISetupDiClassGuidsFromNamePort cost time = 10 mssought 5: COM99
COM4
COM1
<通訊連接埠>
COM98
COM5
Registry method :EnumerateComPortRegistry cost time = 0 mssought 5: COM98 COM99 COM5 COM1 COM4
      Note that: EnumerateComPortSetupAPI_GUID_DEVINTERFACE_COMPORT
would not list CH340 port, which is on an Arduino UNO board. (But the same function could list other CH340 port, if it is not on this Arduino). Besides,  this function could not list Bluetooth virtual com ports.
     
     If you would like to use my code, I suggest you use function
BOOL EnumerateComPortSetupAPISetupDiClassGuidsFromNamePort(UINT *pNumber,   TCHAR *pPortName, int strMaxLen, TCHAR *pFriendName)
     That is the best one which balances speed and detail; but this one are most complicated in implementation. Otherwise, if you want to implement a function which could list com ports as simple as possible, I recommend use the
CreateFilemethod: that is rudimentary, but sufficient.

转载地址:http://ozynx.baihongyu.com/

你可能感兴趣的文章
如何在私有云语境下定义VPC
查看>>
利用企业微信公众平台实现秒级接收微信报警邮件(zabbix3.2.1)
查看>>
记录一下本应用《任您记)APP项目中点击底部导航栏四个按钮,则界面颜色跟着变化及图标字放大效果...
查看>>
tcpcopy+mysql压力测试
查看>>
JAVA面试算法题1
查看>>
opencms Log研究
查看>>
Net简单应用-服务器和客户端之间简单通信
查看>>
Redis命令
查看>>
SSH之端口转发
查看>>
为什么 SSH(安全终端)的端口号是 22 !!
查看>>
Android webservice
查看>>
nginx安装编译,动态添加模块及其各模块的作用
查看>>
iptables只允许指定ip访问本机的指定端口
查看>>
《鬼吹灯之精绝古城》对轻松学编程的启示
查看>>
深入源码大白话理解SpringBoot 究竟是如何跑起来的?
查看>>
jquery ajax请求成功,返回了数据,但是不进success的问题
查看>>
git知识总结
查看>>
智库说 | 杨军:ET城市大脑为城市装上数据“操作系统”
查看>>
HTTP协议
查看>>
C#如何实现在PPT文档中插入、编辑和删除表格的操作
查看>>