¿Cómo puedo obtener una lista de puertos serie disponibles en Win32?


Tengo un código heredado que proporciona una lista de los puertos COM disponibles en el PC llamando al EnumPorts() función y luego filtrado para los nombres de puertos que comienzan con "COM".

Para fines de prueba sería muy útil si pudiera usar este código con algo como com0com, que proporciona pares de puertos COM virtuales en bucle juntos como un módem nulo.

Sin embargo, los puertos com0com no son encontrados por la función EnumPorts() (incluso sin filtrar por "COM"). HyperTerminal y SysInternals PortMon pueden verlos, así que estoy seguro de que está instalado correctamente.

Entonces, ¿hay alguna otra función Win32 que proporcione una lista definitiva de puertos serie disponibles?

Author: GrahamS, 2009-09-07

5 answers

El EnumSerialPorts v1. 20 sugerido por Nick D utiliza nueve diferentes métodos para enumerar los puertos serie! Ciertamente no estamos cortos de opciones, aunque los resultados parecen variar.

Para evitar que otros se molesten, los enumeraré aquí e indicaré su éxito en encontrar los puertos com0com en mi PC (XP Pro SP2):

  1. CreateFile ("COM" + 1->255) como sugiere Wael Dalloul
    ✔ Encontró puertos com0com, tomó 234ms.

  2. QueryDosDevice()
    ✔ Puertos com0com encontrados, tomó 0ms.

  3. GetDefaultCommConfig ("COM" + 1->255)
    ✔ Encontró puertos com0com, tomó 235ms.

  4. "SetupAPI1" usando llamadas a SETUPAPI.DLL
    ✔ Los puertos com0com encontrados, también informaron "nombres amigables", tomaron 15 ms.

  5. "SetupAPI2" usando llamadas a SETUPAPI.DLL
    ports No encontró puertos com0com, informó "nombres amigos", tomó 32ms.

  6. EnumPorts()
    Reported Reportó algunos puertos no COM, no encontró puertos com0com, tomó 15ms.

  7. Usando llamadas WMI
    ✔ Los puertos com0com encontrados, también informaron "nombres amigables", tomaron 47ms.

  8. Base de datos COM usando llamadas a MSPORTS.DLL
    ✔ / Reported Reportó algunos puertos no COM, encontró puertos com0com, tomó 16ms.

  9. Iterar sobre la clave del registro HKEY_LOCAL_MACHINE \ HARDWARE\DEVICEMAP \ SERIALCOMM
    ✔ Encontró puertos com0com, tomó 0ms. Esto es aparentemente lo que usa SysInternals PortMon .

Basado en esos resultados, creo que el método WMI probablemente se adapte mejor a mis requisitos, ya que es relativamente rápido y, como beneficio adicional, también da los nombres amigables (por ejemplo, "Puerto de comunicaciones (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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-22 22:52:47

Parece que no es una tarea sencilla.

Mira esto: 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-07 11:43:33

Puede hacer un bucle, por ejemplo, del 1 al 50 e intentar abrir cada puerto. Si el puerto está disponible, el abierto funcionará. Si el puerto está en uso, aparecerá un error de uso compartido. Si el puerto no está instalado, obtendrá un error de archivo no encontrado.

Para abrir el puerto use CreateFile API:

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

A continuación, compruebe el resultado.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-22 22:53:47

He reorganizado PJ Naughter 's EnumSerialPorts como formas más portátiles e individuales, que es más útil.

Para una mejor compatibilidad, uso C, en lugar de C++.

Si lo necesitas o te interesa, por favor visita el post en mi blogger.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-15 18:33:59

En mi caso, necesito los nombres completos y las direcciones del puerto COM. Tengo puertos serie físicos, puertos serie USB y puertos serie virtuales com0com.

Como sugiere la respuesta aceptada, uso llamadas WMI. SELECT * FROM Win32_PnPEntity buscar todos los dispositivos. Devuelve dispositivos físicos como este, y la dirección se puede analizar desde Caption:

Serial Port for Barcode Scanner (COM13)

Sin embargo, para los puertos com0com Caption es así (sin dirección):

com0com - serial port emulator

SELECT * FROM Win32_SerialPort devuelve direcciones (DeviceID), así como nombres completos (Name). Sin embargo, solo encuentra puertos serie físicos y puertos com0com, no puertos serie USB.

Así que al final, necesito dos llamadas WMI: SELECT * FROM Win32_SerialPort (la dirección es DeviceID) y SELECT * FROM Win32_PnPEntity WHERE Name LIKE '%(COM%' (la dirección se puede analizar desde Caption). He reducido la llamada Win32_PnPEntity, porque solo necesita encontrar dispositivos que no se encontraron en la primera llamada.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-10 11:49:31