SerialPort.GetPortNames()行为

时间:2010-05-02 20:30:21

标签: c# visual-studio-2008 serial-port

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

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

令我惊讶的是,尽管删除了

,仍然可以找到端口名称

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

4 个答案:

答案 0 :(得分:4)

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

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

大多数设备驱动程序返回错误代码,它会生成一个无法捕获的异常,导致程序崩溃。 this feedback article的主题。显然你的设备驱动程序没有这样做,这应该比轰炸你的程序更好。令人鼓舞的是,大多数USB仿真器设备驱动程序都是垃圾。

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

答案 1 :(得分:3)

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

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

答案 2 :(得分:1)

GetPortNames()从注册表项

中读取端口是正确的
HKLM\Hardware\DeviceMap\SerialComm

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

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

那是什么???

我现在找出原因: 这总是在使用www.sysinternals.com上的PortMon后发生。 这个工具是错误的,如果端口在被监视时关闭,则让死端口在注册表中闲置。

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

答案 3 :(得分:0)

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

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

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

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

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