如何获取Win32中可用串行端口的列表?

时间:2009-09-07 11:19:18

标签: winapi serial-port

我有一些遗留代码,它通过调用EnumPorts()函数然后过滤以“COM”开头的端口名称来提供PC上可用COM端口的列表。

出于测试目的,如果我可以将此代码用于com0com之类的代码,它将非常有用,它提供了作为零调制解调器循环在一起的虚拟COM端口对。

然而EnumPorts()函数找不到com0com端口(即使没有过滤“COM”)。 HyperTerminal和SysInternals PortMon都可以看到它们,所以我确定它安装正确。

那么还有其他一些Win32功能可以提供可用串口的确切列表吗?

5 个答案:

答案 0 :(得分:76)

Nick D建议的EnumSerialPorts v1.20使用 9 种不同的方法列出串口!我们肯定不会做出选择,但结果似乎有所不同。

为了省去其他人的麻烦,我会在这里列出并表明他们在我的电脑上找到com0com端口的成功(XP专业版SP2):

    按照Wael Dalloul的建议
  1. CreateFile(“COM”+ 1-> 255) ✔找到com0com端口,耗时234ms。

  2. <强> QueryDosDevice()
    ✔找到com0com端口,耗时0ms。

  3. GetDefaultCommConfig(“COM”+ 1-&gt; 255)
    ✔找到com0com端口,耗时235毫秒。

  4. 使用SETUPAPI.DLL调用“SetupAPI1”
    ✔发现com0com端口,也报告“友好名称”,耗时15ms。

  5. 使用SETUPAPI.DLL调用“SetupAPI2”
    ✘没有找到com0com端口,报告“友好名称”,耗时32ms。

  6. <强> EnumPorts()
    ✘报告了一些非COM端口,没有找到com0com端口,耗时15ms。

  7. 使用WMI通话
    ✔发现com0com端口,也报告“友好名称”,耗时47ms。

  8. 使用MSPORTS.DLL调用的COM数据库
    ✔/✘报告了一些非COM端口,找到了com0com端口,耗时16ms。

  9. 迭代注册表项HKEY_LOCAL_MACHINE \ HARDWARE \ DEVICEMAP \ SERIALCOMM
    ✔找到com0com端口,耗时0ms。这显然是SysInternals PortMon使用的。

  10. 根据这些结果,我认为WMI方法可能最适合我的要求,因为它相对较快,作为奖励,它还提供了友好的名称(例如“通信端口(COM1)”,“com0com - 串口仿真器”)

答案 1 :(得分:11)

看起来这不是一项简单的任务。

看看这个:EnumSerialPorts v1.20

答案 2 :(得分:5)

您可以循环播放例如1到50并尝试打开每个端口。如果端口可用,则打开将起作用。如果端口正在使用中,您将收到共享错误。如果未安装端口,则会收到文件未找到错误。

打开端口使用 CreateFile API:

HANDLE Port = CreateFile(
                  "\\\\.\\COM1",
                  GENERIC_READ | GENERIC_WRITE,
                  0,
                  NULL,
                  OPEN_EXISTING,
                  FILE_ATTRIBUTE_NORMAL,
                  NULL);

然后检查结果。

答案 3 :(得分:1)

我已经将PJ Naughter的EnumSerialPorts重组为更便携和个性化的形式,这更有用。

为了更好地兼容,我使用C而不是C ++。

如果您需要或对此感兴趣,请访问我的博客中的the post

答案 4 :(得分:1)

就我而言,我需要全名和COM端口地址。我有物理串口,USB串口和com0com虚拟串口。

就像接受的答案所示,我使用WMI调用。 SELECT * FROM Win32_PnPEntity找到所有设备。它返回这样的物理设备,地址可以从Caption解析:

Serial Port for Barcode Scanner (COM13)

但是,对于com0com端口Caption是这样的(没有地址):

com0com - serial port emulator

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来电,因为它只需要找到第一次通话中找不到的设备。