Подтвердить что ты не робот

Как получить список доступных последовательных портов в Win32?

У меня есть код устаревшего кода, который предоставляет список доступных COM-портов на ПК, вызывая функцию EnumPorts(), а затем фильтруя для имена портов, начинающиеся с "COM".

В целях тестирования было бы очень полезно, если бы я мог использовать этот код с чем-то вроде com0com, который предоставляет пары виртуальных COM-портов зацикливается вместе как нуль-модем.

Однако порты com0com не найдены функцией EnumPorts() (даже без фильтрации для "COM" ). HyperTerminal и SysInternals PortMon могут видеть их, поэтому я уверен, что он установлен правильно.

Итак, есть ли другая функция Win32, которая предоставляет окончательный список доступных последовательных портов?

4b9b3361

Ответ 1

EnumSerialPorts v1.20, предложенный Nick D, использует девять различных методов для отображения последовательных портов! У нас, конечно, не хватает выбора, хотя результаты, похоже, меняются.

Чтобы сохранить другие проблемы, я перечислил их здесь и указал на их успех в поиске портов com0com на моем ПК (XP Pro SP2):

  • 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, занял 15 мс.

  • Использование вызовов WMI
    ✔ Найденные порты com0com, также сообщаемые "дружественные имена" , заняли 47 мс.

  • База данных COM с использованием вызовов в MSPORTS.DLL
    ✔/✘ Сообщалось о некоторых не COM-портах, найденных портах com0com, заняло 16 мс.

  • Итерации по ключу реестра HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM
    ✔ Найденные порты com0com, заняли 0 мс. По-видимому, это SysInternals PortMon.

На основе этих результатов я считаю, что метод WMI, вероятно, лучше всего подходит для моих требований, поскольку он относительно быстрый, и в качестве бонуса он также дает дружественные имена (например, "Порт связи (COM1)", "com0com - эмулятор последовательного порта" ).

Ответ 2

Похоже, что это не простая задача.

Проверьте это: EnumSerialPorts v1.20

Ответ 3

вы можете сделать цикл, например, от 1 до 50 и попытаться открыть каждый порт. Если порт доступен, откроется функция open. Если порт используется, вы получите сообщение об ошибке обмена. Если порт не установлен, вы получите сообщение об ошибке, не найденной.

чтобы открыть порт, используйте API CreateFile:

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

затем проверьте результат.

Ответ 4

Я реорганизовал PJ Naughter EnumSerialPorts как более портативные и индивидуальные формы, что более полезно.

Для лучшей совместимости я использую C вместо С++.

Если вам это нужно или вас интересует, посетите сообщение в своем блогере.

Ответ 5

В моем случае мне нужны как полные имена, так и адреса 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, потому что ему нужно только найти устройства, которые не были найдены при первом вызове.