Comportement SerialPort.GetPortNames ()

Dans mon application C # 2008, j’utilise la fonction SerialPort.GetPortNames () pour récupérer la liste des ports actuellement disponibles. Ce que j’ai remarqué, c’est que chaque fois que je connecte un périphérique USB, son numéro de port est indiqué dans la liste de mon application et lorsque je le détwig et que je rafraîchis la liste, le numéro de port n’y est plus.

Une phase de l’application consiste à lire / écrire des données de / vers l’appareil en continu. Mon attente est la suivante: si je détwig le périphérique pendant l’opération et récupère la liste de ports actuelle à l’aide de SerialPort.GetPortNames (), le nom du port ne sera pas présent et je pourrai l’utiliser pour décider que le périphérique a été débranché.

À ma grande surprise, le nom du port est toujours trouvé malgré son retrait.

Pourquoi le programme se comporte-t-il comme ça? Le nom du port ne figure pas dans la liste en mode sans communication. Cela a-t-il quelque chose à voir avec le retrait du périphérique lors de la communication?

    Je suppose que vous voulez dire System.IO.Ports.SerialPort.GetPortNames (), parce que je ne pouvais pas trouver une fonction GetPortList () où que ce soit. MSDN indique: “Si le registre contient des données obsolètes ou autrement incorrectes, la méthode GetPortNames renvoie des données incorrectes”, de sorte que le problème réside probablement. J’imagine que Windows ne met pas à jour le registre si le port est toujours “utilisé”, tout comme vous ne pouvez pas supprimer un fichier lorsqu’un programme a un descripteur.

    Si vous souhaitez vérifier si le périphérique est supprimé, vous pouvez le faire avec un appel API Windows ( http://www.pinvoke.net/default.aspx/user32/RegisterDeviceNotification.html ). J’espère que cela pourra aider!

    Vous devez parler de SerialPort.GetPortNames (), “GetPortList” n’a pas de sens. La fonction itère les valeurs dans le registre, écrites par votre pilote de périphérique d’émulateur USB. Vous pouvez avoir un aperçu de Regedit.exe, accédez à HKLM \ Hardware \ DeviceMap \ SerialComm. Détwigz-le, appuyez sur F5. Si le port COM est toujours là, SerialPort ne sait pas mieux que le port toujours présent.

    Il n’y a pas de comportement prescrit quant au comportement d’un pilote de périphérique de port série lorsque le port disparaît soudainement. Les ports série sont très primitifs, ils remontent à une époque où “bug” signifiait un papillon détruisant le télétype. Il n’existe aucune prise en charge matérielle pour Plug-and-Play, la suppression d’un port sous tension étant équivalente à la déconnexion du lecteur de disque lorsque Windows échange le fichier d’échange.

    La plupart des pilotes de périphérique renvoient un code d’erreur, il génère une exception irrécupérable qui bloque votre programme. Le sujet de cet article de feedback . Apparemment, votre pilote de périphérique ne le fait pas, ce qui devrait être préférable au bombardement de votre programme. Encourageant d’ailleurs, la plupart des pilotes de périphérique d’émulateur USB sont totalement indésirables.

    La solution de contournement ultime est simple: placez une petite étiquette sur la fiche “ne vous déconnectez pas pendant l’utilisation!” C’est un peu un problème avec l’USB, la plupart des gens le regardent et disent “hmm, que puis-je en faire?”. Et arriver à la seule réponse et détwigz-le. Après quelques kabooms, ils apprendront à ne plus faire cela.

    Il est correct que GetPortNames() lise les ports à partir de la clé de registre

     HKLM\Hardware\DeviceMap\SerialComm 

    Ceci est automatiquement mis à jour par Windows chaque fois qu’un port est ouvert ou fermé.

    Mais néanmoins, il m’est arrivé qu’il existe un port non existant répertorié dans le registre et renvoyé de GetPortNames() . Lorsque j’essaie d’ouvrir ce port, le message ” Le port XYZ n’existe pas “.

    Qu’est-ce que c’est ???

    J’ai maintenant découvert la raison: Cela se produit toujours après l’utilisation de PortMon à partir de http://www.sysinternals.com. Cet outil est défectueux et laisse le port mort traîner dans le registre si le port est fermé pendant la surveillance.

    Dans ce cas, le seul remède consiste à redémarrer l’ordinateur.

    Comme d’autres l’ont mentionné, cela dépend beaucoup du conducteur. Il ne semble pas y avoir de moyen de vérifier avec l’API .Net si un port renvoyé par GetPortNames () existe réellement et s’il est valide.

    En ce qui concerne la raison pour laquelle les ports se comportent de la sorte, j’ai constaté que certains pilotes USB à série provoquaient le blocage de l’application lorsque le port était débranché subitement.

    D’autres pilotes, souvent ceux qui ne tombent pas en panne, conservent le port dans la liste jusqu’à ce que votre application le ferme, puis il disparaît. Essayer de lire ou d’écrire sur le port obsolète causera (généralement) des délais ou des erreurs. Probablement, pour ne pas mettre l’application en panne, le pilote doit conserver le port périmé tant qu’il est ouvert dans l’application.

    Si vous reconnectez le port, certains pilotes pourront même le reconnecter à votre application, d’autres ne le reconnaîtront pas tant que votre application n’aura pas fermé le port périmé. Ce comportement de reconnexion peut être quelque peu dangereux si le port disparaît à la suite du redémarrage du périphérique, car il se trouverait alors dans un état différent de celui attendu par votre application sans indication évidente de réinitialisation. Au moins, si vous recevez des erreurs du port, vous savez que quelque chose est arrivé.

    J’ai également constaté que si j’oublie de fermer le port, il ne disparaîtra pas de la liste jusqu’à ce que le ramasse-miettes se charge de supprimer l’object SerialPort.