Jak uzyskać listę dostępnych portów szeregowych w Win32?

Mam jakiś kod legacy, który dostarcza listę dostępnych portów COM na PC, wywołując EnumPorts() funkcji, a następnie filtrowanie nazw portów zaczynających się od "COM".

Do celów testowych byłoby bardzo przydatne, gdybym mógł użyć tego kodu z czymś w rodzaju com0com , który dostarcza pary wirtualnych portów COM zapętlonych razem jako null-modem.

Jednak porty com0com nie są znalezione przez funkcję EnumPorts() (nawet bez filtrowania dla "COM"). HyperTerminal i Sysinternals PortMon mogą je zobaczyć, więc jestem pewien, że jest poprawnie zainstalowany.

Czy jest jakaś inna funkcja Win32, która dostarcza definitywną listę dostępnych portów szeregowych?

Author: GrahamS, 2009-09-07

5 answers

Enumserialports v1. 20 zasugerowany przez Nick D używa dziewięciu różnych metod do wyświetlania listy portów szeregowych! Z pewnością nie brakuje nam wyboru, choć wyniki wydają się być różne.

Aby zaoszczędzić innym kłopotów, wymienię ich tutaj i wskażę ich sukces w znalezieniu com0com portów na moim komputerze (XP Pro SP2):

  1. CreateFile ("COM" + 1->255) jak zasugerował Wael Dalloul
    ✔ Znaleziono porty com0com, wzięto 234ms.

  2. QueryDosDevice()
    ✔ Znaleziono porty com0com, zajęło 0ms.

  3. GetDefaultCommConfig ("COM" + 1->255)
    ✔ Znaleziono porty com0com, zajęło 235ms.

  4. "SetupAPI1" używanie wywołań do SETUPAPI.DLL
    ✔ Znaleziono porty com0com, również zgłoszone "przyjazne nazwy", zajęło 15ms.

  5. "SetupAPI2" używanie wywołań do SETUPAPI.DLL
    ✘ Nie znalazł portów com0com, zgłosił "przyjazne nazwy", wziął 32ms.

  6. EnumPorts()
    ✘ Zgłosił niektóre porty NIE-COM, nie znalazł portów com0com, zajął 15ms.

  7. Używanie wywołań WMI
    ✔ Znaleziono porty com0com, również zgłoszone "przyjazne nazwy", zajęło 47ms.

  8. Baza COM wykorzystująca połączenia do MSPORTS.DLL
    ✔ / ✘ Zgłosił niektóre porty nie-COM, znalazł porty com0com, zajął 16ms.

  9. Iteracja nad kluczem rejestru HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM
    ✔ Znaleziono porty com0com, pobrano 0ms. najwyraźniej tego używa SysInternals PortMon.

Bazując na tych wynikach myślę, że metoda WMI prawdopodobnie najbardziej odpowiada moim wymaganiom, ponieważ jest stosunkowo szybka i jako bonus podaje również przyjazne nazwy (np. "Communications Port (COM1)", "com0com - serial port emulator").

 72
Author: GrahamS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-22 22:52:47

Wygląda na to, że nie jest to proste zadanie.

Zobacz to: EnumSerialPorts v1.20

 10
Author: Nick Dandoulakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-07 11:43:33

Możesz utworzyć pętlę na przykład od 1 do 50 i spróbować otworzyć każdy port. Jeśli port jest dostępny, otwarte będzie działać. Jeśli port jest używany, pojawi się błąd udostępniania. Jeśli port nie jest zainstalowany, pojawi się błąd file not found.

Aby otworzyć port użyj CreateFile API:

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

Następnie sprawdź wynik.

 5
Author: Wael Dalloul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-22 22:53:47

Zreorganizowałem PJ EnumSerialPorts jako bardziej przenośne i indywidualne formy, to jest bardziej przydatne.

Dla lepszej kompatybilności używam C, zamiast c++.

Jeśli potrzebujesz lub jesteś zainteresowany, odwiedź post w moim blogerze.

 1
Author: Gaiger Chen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-15 18:33:59

W moim przypadku potrzebuję zarówno pełnych nazw, jak i adresów portów COM. Mam fizyczne porty szeregowe, porty szeregowe USB i wirtualne porty szeregowe com0com.

Jak sugeruje przyjęta odpowiedź, używam połączeń WMI. SELECT * FROM Win32_PnPEntity Znajdź wszystkie urządzenia. Zwraca Fizyczne urządzenia takie jak ten, A adres może być parsowany z Caption:

Serial Port for Barcode Scanner (COM13)

Jednak dla portów com0com Caption jest tak (bez adresu):

com0com - serial port emulator

SELECT * FROM Win32_SerialPort zwraca adresy (DeviceID), a także pełne nazwy (Name). Jednak to znajduje tylko fizyczne porty szeregowe i porty com0com, a nie porty szeregowe USB.

W końcu potrzebuję dwóch wywołań WMI: SELECT * FROM Win32_SerialPort (adres to DeviceID) i SELECT * FROM Win32_PnPEntity WHERE Name LIKE '%(COM%' (adres może być parsowany z Caption). Zawęziłem wywołanie Win32_PnPEntity, ponieważ musi ono znaleźć tylko urządzenia, których nie znaleziono w pierwszym wywołaniu.

 1
Author: Ville-Valtteri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-10 11:49:31