Нужно перечислить все COM порты в системе, будь то виртуальные или реальные. Пробовал EnumPorts - находит не только не все порты (хз почему), но и лишние также, хотя через CreateFile("\\\\.\\COMx",...) ненайденные порты открываются (стояла x86 - работало). Делать CreateFile("\\\\.\\COM%d", ...) от 0 до 255 как-то неэстетично, тем более не найдет уже открытые порты. Есть способ через реестр - ветка HKLM\HARDWARE\SERIALCOMM\, вроде рабочий. Есть какие еще способы? ОС Windows Vista Home Basic x64
А почему способ через CreateFile не находит открытый порт, у меня, например, находит... Просто по GetLastError можно определить код ошибки и уже смотреть есть он в системе или нет. Вопрос тут возникает только по поводу эстетичности такого метода или личных предпочтений... Вот что мой примерчик мне показывает Код (Text): Found COM1 port Found COM2 port Error opening COM3 port, Error is 32: Процесс не может получить доступ к файлу, так как этот файл занят другим процессом. Error opening COM4 port, Error is 2: Не удается найти указанный файл. Пример конечно для x86, но на x64 думаю коды ошибок те же самые...
SUMASBROD Прошу прощения. Находит. Но все же не лучший способ по-моему. Еще насчет поиска названия портов в реестре. Всегда ли они в формате "COM%d" или бывают "\\\\.\\COM%d" или вообще что-либо левое?
Хмм, посмотрел на эту ветку реестра, видимо значения ключей это и есть те названия портов, которые отображаются в диспетчере устройств. В диспетчере я как-то не встречал, чтобы они по-другому назывались. Но на правоту не претендую.
Проверял, могут быть названия разные. Еще вот такое нашел: Но в этом случае непонятно, как следует открывать их. Обычно порты 1-9 открываются передачей в CreateFile строки "COM%d", а с номером выше 9 только передачей "\\\\.\\COM%d", но раз названия разные могут быть, то хз почему нельзя открыть порт CreateFile("COM13"), а только CreateFile("\\\\.\\COM13").
Например, так: Код (Text): DWORD dwGuids = 0; SetupDiClassGuidsFromName( L"Ports", 0, 0, &dwGuids ); GUID* pGuids = new GUID[dwGuids]; SetupDiClassGuidsFromName( L"Ports", pGuids, dwGuids, &dwGuids ); HDEVINFO hDevInfoSet = SetupDiGetClassDevs( pGuids, NULL, NULL, DIGCF_PRESENT ); delete [] pGuids; BOOL bMoreItems = TRUE; int nIndex = 0; SP_DEVINFO_DATA devInfo; devInfo.cbSize = sizeof( SP_DEVINFO_DATA ); while( SetupDiEnumDeviceInfo( hDevInfoSet, nIndex, &devInfo ) && ( iIndex != -1 ) ) { HKEY hDeviceKey = SetupDiOpenDevRegKey( hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE ); if( hDeviceKey ) { TCHAR pszPortName[256]; TCHAR pszFriendlyName[256]; DWORD dwSize = sizeof(pszPortName); DWORD dwType = 0; if( ( ( RegQueryValueEx( hDeviceKey, L"PortName", NULL, &dwType, reinterpret_cast<LPBYTE>( pszPortName ), &dwSize ) == ERROR_SUCCESS ) ) && ( dwType == REG_SZ ) ) { size_t nLen = wcslen( pszPortName ); if (nLen > 3) { if ( _wcsnicmp( pszPortName, L"COM", 3 ) == 0 ) { TCHAR lsStr[256]; dwSize = sizeof( pszFriendlyName ); SetupDiGetDeviceRegistryProperty( hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, reinterpret_cast<PBYTE>( pszFriendlyName ), dwSize, &dwSize ); wsprintf( lsStr, L"%s : %s", pszPortName, pszFriendlyName ); } } } RegCloseKey(hDeviceKey); } ++nIndex; } SetupDiDestroyDeviceInfoList( hDevInfoSet );
Полагаю, ожидается мое слово. Нужно это было затем, чтобы, например, определить на каком из портов стоит устройство для общения с ним. Как это определить, если не знать списка портов? Пример: на моем ноутбуке стоит встроенный модем, как оказалось, на COM3. К сожалению, мой браузер не позволяет полноценным образом просматривать содержимое под тегом code. См. цитату в #5. Любые другие варианты 'определения' списка портов не являются переносимыми между версиями ОС и поэтому их следует использовать только как вспомогательные.
KeSqueer WMI - Windows Management Instrumentation. Есть везде начиная с W2K. Список портов (и вообще практически любой системной информации) можно получить простым запросом, похожим на SQL SELECT * FROM Win32_SerialPort