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

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

出于testing的目的,如果我可以使用com0com这样的代码来提供这些代码,它将提供成对的虚拟COM端口作为一个空调制解调器。

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

那么还有其他一些Win32函数提供了可用的串行端口的权威列表吗?

Nick Dbuild议的EnumSerialPorts v1.20使用九种不同的方法列出串行端口! 虽然结果似乎有所不同,但我们当然并不缺乏select。

为了节省他人的麻烦,我将在这里列出他们,并指出他们在我的电脑(XP Pro SP2)上findcom0com端口的成功:

  1. 如Wael Dalloulbuild议的CreateFile(“COM”+ 1-> 255)
    ✔findcom0com端口,花了234ms。

  2. QueryDosDevice()
    ✔findcom0com端口,花了0ms。

  3. GetDefaultCommConfig(“COM”+ 1-> 255)
    ✔findcom0com端口,花了235ms。

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

  5. 使用SETUPAPI.DLL调用“SetupAPI2”
    ✘没有findcom0com端口,报告“友好的名字”,花了32毫秒。

  6. EnumPorts()
    ✘报告了一些非COM端口,没有findcom0com端口,花了15ms。

  7. 使用WMI调用
    ✔发现com0com的端口,也报“友好的名字”,耗时47毫秒。

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

  9. 迭代registry项HKEY_LOCAL_MACHINE \ HARDWARE \ DEVICEMAP \ SERIALCOMM
    ✔findcom0com端口,花了0ms。 这显然是SysInternals PortMon使用的。

基于这些结果,我认为WMI方法可能最适合我的要求,因为它相对较快,作为一个奖励它还给出友好的名称(例如“通信端口(COM1)”,“com0com – 串行端口仿真器”)。

看来,这不是一个简单的任务。

看看这个: EnumSerialPorts v1.20

你可以循环例如从1到50,并尝试打开每个端口。 如果端口可用,则打开将工作。 如果端口正在使用中,则会出现共享错误。 如果端口没有安装,你会得到一个文件未find错误。

打开该端口使用CreateFile API:

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

然后检查结果。

我已经将PJ Naugh的EnumSerialPorts重组为更便携的个人forms,这是更有用的。

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

如果您需要或有兴趣,请访问我的博客文章。

在我的情况下,我需要全名和COM端口地址。 我有物理串行端口,USB串行端口和com0com虚拟串行端口。

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

 Serial Port for Barcode Scanner (COM13) 

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

 com0com - serial port emulator 

SELECT * FROM Win32_SerialPort返回地址( DeviceID )以及全名( Name )。 但是,它只能find物理串行端口和com0com端口,而不是USB串行端口。

所以最后,我需要两个WMI调用: SELECT * FROM Win32_SerialPort (地址是DeviceID )和SELECT * FROM Win32_PnPEntity WHERE Name LIKE '%(COM%' (地址可以从Captionparsing)我已经缩小了Win32_PnPEntity调用,因为它只需要查找在第一次调用中找不到的设备。