Поведение SerialPort.GetPortNames () - PullRequest
1 голос
/ 03 мая 2010

В моем приложении на C # 2008 я использую функцию SerialPort.GetPortNames () для получения списка доступных на данный момент портов. Что я заметил, так это то, что когда я подключаю USB-устройство, его номер порта отображается в списке приложения, а когда я отключаю его и обновляю список, номера порта больше нет.

Одна фаза приложения включает непрерывное чтение / запись данных с / на устройство. Теперь я ожидаю, что если я отключу устройство во время операции и получу текущий список портов, используя SerialPort.GetPortNames (), имя порта не будет там, и я могу использовать его, чтобы принять решение о том, что устройство отключено.

К моему удивлению, имя порта все еще найдено, несмотря на то, что оно было удалено

Почему программа ведет себя так? Имя порта не отображается в режиме отсутствия связи. Это как-то связано с удалением устройства во время связи?

Ответы [ 4 ]

4 голосов
/ 03 мая 2010

У вас есть , чтобы говорить о SerialPort.GetPortNames (), "GetPortList" не имеет смысла. Функция перебирает значения в реестре, записанные там вашим драйвером устройства USB-эмулятора. Вы можете посмотреть с помощью Regedit.exe, перейдите к HKLM \ Hardware \ DeviceMap \ SerialComm. Отключите его, нажмите F5, если COM-порт все еще там, то SerialPort не знает ничего лучше, чем тот, который все еще присутствует.

Нет никакого предписанного поведения относительно того, как должен вести себя драйвер устройства последовательного порта, когда порт внезапно исчезает. Последовательные порты очень примитивны, они восходят к эпохе, когда «ошибка» означала сумеречную болтовню телетайпа. Аппаратная поддержка Plug and Play вообще не поддерживается, удаление порта при включенном питании эквивалентно отключению диска во время замены Windows на файл подкачки.

Большинство драйверов устройств возвращают код ошибки, он генерирует неуловимое исключение, которое приводит к сбою вашей программы. Тема этой статьи обратной связи . Очевидно, ваш драйвер устройства не делает этого, что должно быть предпочтительнее, чем бомбардировка вашей программы. Поощряя, между прочим, большинство драйверов устройств USB-эмуляторов совершенно бесполезны.

Окончательный обходной путь прост: установите на штекер небольшую метку "не отключайте во время использования!" Это своего рода проблема с USB, большинство людей смотрят на нее и говорят: «Хм, а что я могу с ней сделать?». И получите единственный ответ и отключите его. После пары кабумов они научатся больше этого не делать.

3 голосов
/ 03 мая 2010

Я предполагаю, что вы имеете в виду System.IO.Ports.SerialPort.GetPortNames (), потому что я нигде не смог найти функцию GetPortList (). MSDN говорит: «Если реестр содержит устаревшие или иным образом некорректные данные, то метод GetPortNames вернет неверные данные», так что, вероятно, в этом и заключается проблема. Я предполагаю, что Windows не обновляет реестр, если порт все еще используется, точно так же, как вы не можете удалить файл, когда программа имеет дескриптор.

Если вы хотите проверить, удалено ли устройство, вы можете сделать это с помощью вызова API Windows (http://www.pinvoke.net/default.aspx/user32/RegisterDeviceNotification.html). Надеюсь, это поможет!

1 голос
/ 01 августа 2013

Правильно, что GetPortNames() читает порты из ключа реестра

HKLM\Hardware\DeviceMap\SerialComm

Это автоматически обновляется Windows каждый раз, когда порт открывается или закрывается.

Но, тем не менее, мне пришло в голову, что в Реестре есть несуществующий Порт, а также возвращенный из GetPortNames(). Когда я пытаюсь открыть этот порт, я получаю « Порт XYZ не существует ».

Что это такое?

Теперь я выяснил причину: Это происходит всегда после использования PortMon от www.sysinternals.com. Этот инструмент глючит и позволяет мертвому порту зависать в реестре, если порт закрыт во время мониторинга.

В этом случае единственным выходом является перезагрузка компьютера.

0 голосов
/ 26 мая 2014

Как уже упоминали другие, это очень зависит от драйвера. Похоже, нет способа проверить с помощью .Net API, существует ли порт, возвращенный GetPortNames (), на самом деле и действителен.

Что касается того, почему порты ведут себя так, я обнаружил, что некоторые драйверы USB-to-serial вызывают сбой приложения при внезапном отключении порта.

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

Если вы снова подключите порт, некоторые драйверы смогут даже повторно подключить его к вашему приложению, другие не будут распознавать порт, пока ваше приложение не закроет устаревший порт. Такое поведение при повторном подключении может быть несколько опасным, если порт исчез из-за перезагрузки устройства, потому что тогда он внезапно окажется в другом состоянии, чем ожидает ваше приложение, без явного указания на его сброс. По крайней мере, если вы получаете ошибки из порта, вы знаете, что что-то произошло.

Я также обнаружил, что если я забуду закрыть порт, он не исчезнет из списка до тех пор, пока сборщик мусора не сможет утилизировать объект SerialPort.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...