Получение списка COM портов

Тема в разделе "WASM.X64", создана пользователем KeSqueer, 25 окт 2008.

  1. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Нужно перечислить все COM порты в системе, будь то виртуальные или реальные.
    Пробовал EnumPorts - находит не только не все порты (хз почему), но и лишние также, хотя через CreateFile("\\\\.\\COMx",...) ненайденные порты открываются (стояла x86 - работало).
    Делать CreateFile("\\\\.\\COM%d", ...) от 0 до 255 как-то неэстетично, тем более не найдет уже открытые порты.
    Есть способ через реестр - ветка HKLM\HARDWARE\SERIALCOMM\, вроде рабочий.
    Есть какие еще способы?
    ОС Windows Vista Home Basic x64
     
  2. SUMASBROD

    SUMASBROD Member

    Публикаций:
    0
    Регистрация:
    8 май 2007
    Сообщения:
    64
    А почему способ через CreateFile не находит открытый порт, у меня, например, находит...
    Просто по GetLastError можно определить код ошибки и уже смотреть есть он в системе или нет.
    Вопрос тут возникает только по поводу эстетичности такого метода или личных предпочтений...

    Вот что мой примерчик мне показывает
    Код (Text):
    1. Found COM1 port
    2. Found COM2 port
    3. Error opening COM3 port, Error is 32: Процесс не может получить доступ к файлу, так как этот файл занят другим процессом.
    4. Error opening COM4 port, Error is 2: Не удается найти указанный файл.
    Пример конечно для x86, но на x64 думаю коды ошибок те же самые...
     
  3. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    SUMASBROD
    Прошу прощения. Находит. Но все же не лучший способ по-моему.

    Еще насчет поиска названия портов в реестре. Всегда ли они в формате "COM%d" или бывают "\\\\.\\COM%d" или вообще что-либо левое?
     
  4. SUMASBROD

    SUMASBROD Member

    Публикаций:
    0
    Регистрация:
    8 май 2007
    Сообщения:
    64
    Хмм, посмотрел на эту ветку реестра, видимо значения ключей это и есть те названия портов, которые отображаются в диспетчере устройств. В диспетчере я как-то не встречал, чтобы они по-другому назывались. Но на правоту не претендую.
     
  5. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Проверял, могут быть названия разные. Еще вот такое нашел:
    Но в этом случае непонятно, как следует открывать их. Обычно порты 1-9 открываются передачей в CreateFile строки "COM%d", а с номером выше 9 только передачей "\\\\.\\COM%d", но раз названия разные могут быть, то хз почему нельзя открыть порт CreateFile("COM13"), а только CreateFile("\\\\.\\COM13").
     
  6. deshton

    deshton New Member

    Публикаций:
    0
    Регистрация:
    5 янв 2009
    Сообщения:
    1
    А зачем вам собственно это надо, не могу понять.
     
  7. LocTb

    LocTb New Member

    Публикаций:
    0
    Регистрация:
    11 окт 2004
    Сообщения:
    54
    Например, так:
    Код (Text):
    1.     DWORD dwGuids = 0;
    2.  
    3.     SetupDiClassGuidsFromName( L"Ports", 0, 0, &dwGuids );
    4.  
    5.     GUID* pGuids = new GUID[dwGuids];
    6.  
    7.     SetupDiClassGuidsFromName( L"Ports", pGuids, dwGuids, &dwGuids );
    8.  
    9.     HDEVINFO hDevInfoSet = SetupDiGetClassDevs( pGuids, NULL, NULL, DIGCF_PRESENT );
    10.  
    11.     delete [] pGuids;
    12.  
    13.     BOOL bMoreItems = TRUE;
    14.     int nIndex = 0;
    15.  
    16.     SP_DEVINFO_DATA devInfo;
    17.  
    18.     devInfo.cbSize = sizeof( SP_DEVINFO_DATA );
    19.  
    20.     while( SetupDiEnumDeviceInfo( hDevInfoSet, nIndex, &devInfo ) && ( iIndex != -1 ) )
    21.     {
    22.         HKEY hDeviceKey = SetupDiOpenDevRegKey( hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE );
    23.  
    24.         if( hDeviceKey )
    25.         {
    26.             TCHAR pszPortName[256];
    27.             TCHAR pszFriendlyName[256];
    28.  
    29.             DWORD dwSize = sizeof(pszPortName);
    30.             DWORD dwType = 0;
    31.  
    32.             if( (
    33.                 ( RegQueryValueEx( hDeviceKey, L"PortName", NULL, &dwType, reinterpret_cast<LPBYTE>( pszPortName ), &dwSize ) == ERROR_SUCCESS ) ) &&
    34.                 ( dwType == REG_SZ )
    35.                 )
    36.             {
    37.                 size_t nLen = wcslen( pszPortName );
    38.  
    39.                 if (nLen > 3)
    40.                 {
    41.                     if ( _wcsnicmp( pszPortName, L"COM", 3 ) == 0 )
    42.                     {
    43.                         TCHAR lsStr[256];
    44.  
    45.                         dwSize = sizeof( pszFriendlyName );
    46.  
    47.                         SetupDiGetDeviceRegistryProperty( hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, reinterpret_cast<PBYTE>( pszFriendlyName ), dwSize, &dwSize );
    48.  
    49.                         wsprintf( lsStr, L"%s : %s", pszPortName, pszFriendlyName );
    50.                     }
    51.                 }
    52.             }
    53.  
    54.             RegCloseKey(hDeviceKey);
    55.         }
    56.  
    57.         ++nIndex;
    58.     }
    59.  
    60.     SetupDiDestroyDeviceInfoList( hDevInfoSet );
     
  8. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Полагаю, ожидается мое слово.
    Нужно это было затем, чтобы, например, определить на каком из портов стоит устройство для общения с ним. Как это определить, если не знать списка портов? Пример: на моем ноутбуке стоит встроенный модем, как оказалось, на COM3.
    К сожалению, мой браузер не позволяет полноценным образом просматривать содержимое под тегом code. См. цитату в #5. Любые другие варианты 'определения' списка портов не являются переносимыми между версиями ОС и поэтому их следует использовать только как вспомогательные.
     
  9. Partner

    Partner Павел

    Публикаций:
    0
    Регистрация:
    28 фев 2008
    Сообщения:
    917
    Адрес:
    Los Angeles
    WMI рассматривал ?
     
  10. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Partner
    Прошу прощения, что это есть и как в плане совместимости? Поискал бы сам, да трафик дорогой.
     
  11. Partner

    Partner Павел

    Публикаций:
    0
    Регистрация:
    28 фев 2008
    Сообщения:
    917
    Адрес:
    Los Angeles
    KeSqueer
    WMI - Windows Management Instrumentation. Есть везде начиная с W2K.
    Список портов (и вообще практически любой системной информации) можно получить простым запросом, похожим на SQL
    SELECT * FROM Win32_SerialPort
     
  12. Partner

    Partner Павел

    Публикаций:
    0
    Регистрация:
    28 фев 2008
    Сообщения:
    917
    Адрес:
    Los Angeles
    Для W2K и выше также можно посмотреть в реестре
    HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM