如何获取 Win32 中可用串行端口的列表?
我有一些遗留代码,通过调用 EnumPorts()
函数,然后过滤以“COM”开头的端口名称。
出于测试目的,如果我可以将此代码与 com0com 之类的东西一起使用,它会提供虚拟对COM 端口作为零调制解调器循环在一起。
但是,EnumPorts()
函数找不到 com0com 端口(即使没有过滤“COM”)。超级终端和 SysInternals PortMon 都可以看到它们,所以我确信它安装正确。
那么还有其他一些 Win32 函数可以提供可用串行端口的明确列表吗?
I have some legacy code that provides a list of the available COM ports on the PC by calling the EnumPorts()
function and then filtering for the port names that start with "COM".
For testing purposes it would be very useful if I could use this code with something like com0com, which provides pairs of virtual COM ports looped together as a null-modem.
However the com0com ports are not found by the EnumPorts()
function (even without filtering for "COM"). HyperTerminal and SysInternals PortMon can both see them, so I'm sure it is installed correctly.
So is there some other Win32 function that provides a definitive list of available serial ports?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
Nick D 建议的 EnumSerialPorts v1.20 使用九种不同的方法来列出串行端口!我们当然不缺少选择,尽管结果似乎有所不同。
为了省去其他人的麻烦,我将在这里列出它们,并表明它们在我的 PC (XP Pro SP2) 上成功找到
com0com
端口:CreateFile("COM" + 1 ->255) 根据 Wael Dalloul 的建议
✔ 找到 com0com 端口,花费了 234 毫秒。
QueryDosDevice()
✔ 找到 com0com 端口,花费了 0 毫秒。
GetDefaultCommConfig("COM" + 1->255)
✔ 找到 com0com 端口,耗时 235 毫秒。
“SetupAPI1”使用对 SETUPAPI.DLL 的调用
✔ 找到 com0com 端口,还报告“友好名称”,花费了 15 毫秒。
“SetupAPI2”使用对 SETUPAPI.DLL 的调用
✘ 未找到 com0com 端口,报告“友好名称”,耗时 32 毫秒。
EnumPorts()
✘ 报告一些非COM端口,没有找到com0com端口,花了15ms。
使用 WMI 调用
✔ 找到 com0com 端口,还报告“友好名称”,花费了 47 毫秒。
使用 MSPORTS.DLL 调用的 COM 数据库
✔/✘ 报告了一些非 COM 端口,找到了 com0com 端口,花费了 16 毫秒。
迭代注册表项 HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM
✔ 找到 com0com 端口,花费了 0 毫秒。这显然是 SysInternals PortMon 使用的。
基于这些结果,我认为 WMI 方法可能最适合我的要求,因为它相对较快,而且它还提供了友好的名称(例如“通信端口 (COM1)”、“com0com - 串行端口模拟器”)。
The EnumSerialPorts v1.20 suggested by Nick D uses nine different methods to list the serial ports! We're certainly not short on choice, though the results seem to vary.
To save others the trouble, I'll list them here and indicate their success in finding the
com0com
ports on my PC (XP Pro SP2):CreateFile("COM" + 1->255) as suggested by Wael Dalloul
✔ Found com0com ports, took 234ms.
QueryDosDevice()
✔ Found com0com ports, took 0ms.
GetDefaultCommConfig("COM" + 1->255)
✔ Found com0com ports, took 235ms.
"SetupAPI1" using calls to SETUPAPI.DLL
✔ Found com0com ports, also reported "friendly names", took 15ms.
"SetupAPI2" using calls to SETUPAPI.DLL
✘ Did not find com0com ports, reported "friendly names", took 32ms.
EnumPorts()
✘ Reported some non-COM ports, did not find com0com ports, took 15ms.
Using WMI calls
✔ Found com0com ports, also reported "friendly names", took 47ms.
COM Database using calls to MSPORTS.DLL
✔/✘ Reported some non-COM ports, found com0com ports, took 16ms.
Iterate over registry key HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM
✔ Found com0com ports, took 0ms. This is apparently what SysInternals PortMon uses.
Based on those results I think the WMI method probably suits my requirements best as it is relatively fast and as a bonus it also gives the friendly names (e.g. "Communications Port (COM1)", "com0com - serial port emulator").
看来这不是一个简单的任务。
看看这个:EnumSerialPorts v1.20
It appears that it's not a simple task.
Check out this: EnumSerialPorts v1.20
例如,您可以从 1 到 50 进行循环,并尝试打开每个端口。如果端口可用,则打开即可。如果端口正在使用中,您将收到共享错误。如果未安装该端口,您将收到文件未找到错误。
使用CreateFile API 打开端口:
然后检查结果。
you can make loop for example from 1 to 50 and try to open each port. If the port is available, the open will work. If the port is in use, you'll get a sharing error. If the port is not installed, you'll get a file not found error.
to open the port use CreateFile API:
then check the result.
现在可在 Windows 中使用,GetCommPorts 可以直接返回通讯端口列表
您需要添加此代码才能正确链接该函数
It's available now in Windows, GetCommPorts can directly return a list of comm ports
you will need to add this code in order to link the function correctly
就我而言,我需要全名和 COM 端口地址。我有物理串口、USB串口和com0com虚拟串口。
正如已接受的答案所示,我使用 WMI 调用。
SELECT * FROM Win32_PnPEntity
查找所有设备。它返回这样的物理设备,并且可以从Caption
解析地址:但是,对于 com0com 端口
Caption
如下(无地址):SELECT * FROM Win32_SerialPort
返回地址 (DeviceID
) 以及全名 (Name
)。但是,它只找到物理串行端口和com0com端口,而不是USB串行端口。所以最后,我需要两个 WMI 调用:
SELECT * FROM Win32_SerialPort
(地址为DeviceID
)和SELECT * FROM Win32_PnPEntity WHERE Name LIKE '%(COM% '
(地址可以从Caption
解析)。我已经缩小了Win32_PnPEntity
调用的范围,因为它只需要查找第一次未找到的设备。 此 C++代码可用于查找所有串行端口:
In my case, I need both the full names and COM port addresses. I have physical serial ports, USB serial ports, and com0com virtual serial ports.
Like the accepted answer suggests, I use WMI calls.
SELECT * FROM Win32_PnPEntity
find all devices. It returns physical devices like this, and address can be parsed fromCaption
:However, for com0com ports
Caption
is like this (no address):SELECT * FROM Win32_SerialPort
returns addresses (DeviceID
), as well as full names (Name
). However, it only finds physical serial ports and com0com ports, not USB serial ports.So in the end, I need two WMI calls:
SELECT * FROM Win32_SerialPort
(address isDeviceID
) andSELECT * FROM Win32_PnPEntity WHERE Name LIKE '%(COM%'
(address can be parsed fromCaption
). I have narrowed down theWin32_PnPEntity
call, because it only needs to find devices that were not found in the first call.This C++ code can be used to find all serial ports:
我将 PJ Naughter 的 EnumSerialPorts 重新组织为更便携和个性化的形式,这更有用。
为了更好的兼容性,我使用 C,而不是 C++。
如果您需要或感兴趣,请访问我的博客中的帖子。
I have reorganized PJ Naughter 's EnumSerialPorts as more portable and individual forms, that is more useful.
For better in compatibility, I use C, instead of C++.
If you need or be interested in it, please visit the post in my blogger.