SerialPort.GetPortNames()行为

在我的C#2008应用程序中,我使用SerialPort.GetPortNames()函数来检索当前可用端口的列表。 我注意到的是,当我插入USB设备时,它的端口号显示在我的应用程序列表中,当我拔下它并刷新列表时,端口号不再存在。

该应用的一个阶段涉及连续地从/向设备读/写数据。 现在,我的期望是,如果我在操作期间拔出设备并使用SerialPort.GetPortNames()获取当前端口列表,则端口名称将不在那里,我可以使用它来确定设备已被拔出。

令我惊讶的是,尽管删除了端口名称,仍然可以找到它

为什么程序表现得像这样? 在无通信模式下,未列出端口名称。 是否与设备在通信时被删除有关?

我假设你的意思是System.IO.Ports.SerialPort.GetPortNames(),因为我无法在任何地方找到GetPortList()函数。 MSDN说:“如果注册表包含陈旧或不正确的数据,那么GetPortNames方法将返回不正确的数据”,因此这可能是问题所在。 我想如果端口仍在“使用”,Windows不会更新注册表,就像程序有句柄时无法删除文件一样。

如果要测试是否删除了设备,可以使用Window API调用( http://www.pinvoke.net/default.aspx/user32/RegisterDeviceNotification.html )进行测试。 希望有所帮助!

必须谈论SerialPort.GetPortNames(),“GetPortList”没有意义。 该函数迭代注册表中的值,由USB仿真器设备驱动程序写入。 您可以查看Regedit.exe,导航到HKLM \ Hardware \ DeviceMap \ SerialComm。 拔掉它,按F5键,如果COM端口仍在那里,那么SerialPort不知道还有什么比仍然存在的端口更好。

当端口突然消失时,串行端口设备驱动程序的行为方式没有规定的行为。 串口是非常原始的,它们可以追溯到一个“虫子”意味着飞蛾弄乱电传打字机的时代。 即插即用没有任何硬件支持,在打开电源时移除端口相当于在Windows交换到分页文件时拔出磁盘驱动器。

大多数设备驱动程序返回错误代码,它会生成一个无法捕获的exception,导致程序崩溃。 这篇反馈文章的主题。 显然你的设备驱动程序没有这样做,这应该比轰炸你的程序更可取。 令人鼓舞的是,大多数USB仿真器设备驱动程序都是完全垃圾。

最终的解决方法很简单:在插头上放一个小标签“在使用时不要断开连接!” 这有点像USB的问题,大多数人都会看着它,然后“嗯,我该怎么办?”。 并得出唯一的答案并拔掉它。 经过几次kabooms,他们将学会不再那样做了。

GetPortNames()从Registry键读取端口是正确的

 HKLM\Hardware\DeviceMap\SerialComm 

每次打开或关闭端口时,Windows都会自动更新。

但是,在我看来,注册表中列出了一个不存在的端口,并且还从GetPortNames()返回。 当我尝试打开此端口时,我得到“ 端口XYZ不存在 ”。

那是什么 ???

我现在发现了原因:这种情况总是在使用www.sysinternals.com上的PortMon之后发生。 这个工具有问题,如果端口在被监视时关闭,则让死端口挂在注册表中。

在这种情况下,唯一的补救措施是重新启动计算机。

正如其他人所提到的那样,它非常适合驾驶员。 似乎没有办法检查.Net API是否GetPortNames()返回的端口实际存在且有效。

至于为什么端口的行为如此,我发现一些USB转串口驱动程序会导致应用程序在突然拔出端口时崩溃。

其他驱动程序(通常是那些不会崩溃的驱动程序)会将端口保留在列表中,直到应用程序关闭它,然后它就会消失。 尝试读取或写入陈旧端口将(通常)导致超时或错误。 据推测,为了不使应用程序崩溃,驱动程序需要在应用程序中仍然打开时保持旧的端口。

如果再次插入端口,某些驱动程序甚至可以将其重新连接到您的应用程序,其他驱动程序将无法识别该端口,直到您的应用程序关闭旧的端口。 如果端口因设备重新启动而消失,这种重新连接行为可能会有些危险,因为它会突然处于与应用程序预期不同的状态,而没有明显指示它已重置。 至少如果你从端口收到错误,你就知道发生了什么事。

我还发现,如果我忘记关闭端口,它将不会从列表中消失,直到垃圾收集器绕过处理SerialPort对象。