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

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

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

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

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

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

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

  1. CreateFile («COM» + 1-> 255), как предложил Ваэль Даллул
    ✔ Найденные порты com0com, заняли 234 мс.

  2. QueryDosDevice ()
    ✔ Найденные порты com0com, заняли 0 мс.

  3. GetDefaultCommConfig (“COM” + 1-> 255)
    ✔ Найденные порты com0com, заняли 235 мс.

  4. «SetupAPI1», используя вызовы SETUPAPI.DLL
    ✔ Найденные порты com0com, также сообщаемые «дружественные имена», заняли 15 мс.

  5. «SetupAPI2», используя вызовы SETUPAPI.DLL
    ✘ Не удалось найти порты com0com, сообщает «дружественные имена», заняло 32 мс.

  6. EnumPorts ()
    ✘ Сообщалось о некоторых не COM-портах, не обнаруживших портов com0com, заняло 15 мс.

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

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

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

Основываясь на этих результатах, я думаю, что метод WMI, вероятно, лучше всего подходит для моих требований, поскольку он относительно быстрый, и в качестве бонуса он также дает дружественные имена (например, «Communication Port (COM1)», «com0com – эмулятор последовательного порта»).

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

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

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

для открытия порта используйте API CreateFile :

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

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

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

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

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

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

  • Как хранить и извлекать учетные данные из диспетчера учетных данных Windows Vault?
  • Как использовать FolderBrowserDialog из приложения WPF
  • Ограничивает ли Windows 7 доступ к папкам, как Vista?
  • IntPtr, SafeHandle и HandleRef - Разъяснения
  • Как получить исполняемое имя приложения в WindowsC ++ / CLI?
  • Как я могу обернуть API-интерфейс FindXFile в шаблон Iterator в стиле STL в C ++?
  • Программно предотвратить запуск заставки Windows
  • Как я рекурсивно создаю папку в Win32?
  • Что происходит, когда вы закрываете консольное приложение c ++
  • Как программно получить версию DLL или EXE-файла?
  • Как проверить, запущена ли программа с консоли?
  • Давайте будем гением компьютера.