SerialPort.GetPortNames() 行为
在我的 C# 2008 应用程序中,我使用 SerialPort.GetPortNames() 函数来检索当前可用端口的列表。我注意到,当我插入 USB 设备时,它的端口号会显示在我的应用程序的列表中,而当我拔下它并刷新列表时,端口号不再存在。
应用程序的一个阶段涉及连续从设备读取数据/向设备写入数据。现在,我的期望是,如果我在操作期间拔下设备并使用 SerialPort.GetPortNames() 获取当前端口列表,则端口名称将不存在,我可以使用它来做出设备已拔出的决定。
令我惊讶的是,尽管已删除端口名称,但仍然可以找到
为什么程序会这样?处于非通信模式时,不会列出端口名称。这是否与设备在通信时被移除有关?
In my C# 2008 application, I use the SerialPort.GetPortNames() function to retrieve the list of currently available ports. What I have noticed is, when ever I plug in a USB device, it's port number i s shown in the list on my Application and when I unplug it and refresh the list, the port number is no longer there.
One phase of the application involves reading/writing data from/to the device continuously. Now, my expectation is, If I unplug the device during the operation and get the current Port list using SerialPort.GetPortNames(), the Port Name will not be there and I can use that to make the decision that the device has been unplugged.
To my surprise, the Port name is still found despite having it removed
Why is the program behaving like this? The port name isn't listed when in no-communication mode. Does it have something to do with the device being removed when it's communicating?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您必须谈论SerialPort.GetPortNames(),“GetPortList”没有意义。该函数迭代注册表中的值,这些值是由 USB 仿真器设备驱动程序写入的。您可以使用 Regedit.exe 查看,导航至 HKLM\Hardware\DeviceMap\SerialComm。拔掉它,按 F5,如果 COM 端口仍然存在,那么 SerialPort 不会比仍然存在的端口更好地知道。
对于串行端口设备驱动程序在端口突然消失时应如何表现,没有规定的行为。串行端口非常原始,可以追溯到“bug”意味着飞蛾弄坏电传打字机的时代。根本不支持即插即用的硬件,在打开电源的情况下删除端口相当于在 Windows 交换到分页文件时拔出磁盘驱动器。
大多数设备驱动程序都会返回错误代码,它会生成无法捕获的异常,导致程序崩溃。 此反馈的主题文章。显然你的设备驱动程序不会这样做,这应该比轰炸你的程序更好。顺便说一句,令人鼓舞的是,大多数 USB 仿真器设备驱动程序都是垃圾。
最终的解决方法很简单:在插头上贴一个小标签“使用时请勿断开连接!”这有点像 USB 的问题,大多数人看到它都会说“嗯,我能用它做什么?”。找到唯一的答案并拔掉电源。经过几次轰动之后,他们就会学会不再这样做。
You have to be talking about SerialPort.GetPortNames(), "GetPortList" doesn't make sense. The function iterates values in the registry, written there by your USB emulator device driver. You can have a look-see with Regedit.exe, navigate to HKLM\Hardware\DeviceMap\SerialComm. Unplug it, press F5, if the COM port is still there then SerialPort doesn't know any better than the port still being present.
There is no prescribed behavior as to how a serial port device driver should behave when the port suddenly vanishes. Serial ports are very primitive, they date back to an era where "bug" meant a moth gumming up the teletype. There is no hardware support at all for Plug and Play, removing a port with the power turned on is equivalent to unplugging the disk drive while Windows is swapping to the paging file.
Most device drivers return an error code, it generates an uncatchable exception that crashes your program. The subject of this feedback article. Apparently your device driver doesn't do that, which ought to be preferable over bombing your program. Encouraging btw, most USB emulator device drivers are utter junk.
The ultimate workaround is simple: put a little tag on the plug "don't disconnect while in use!" It's kinda of a problem with USB, most people look at it and go "hmm, what can I do with it?". And arrive at the only answer and unplug it. After a couple of kabooms, they'll learn to not do that anymore.
我假设您的意思是 System.IO.Ports.SerialPort.GetPortNames(),因为我在任何地方都找不到 GetPortList() 函数。 MSDN 说:“如果注册表包含过时的或其他不正确的数据,那么 GetPortNames 方法将返回不正确的数据”,所以这可能就是问题所在。我猜想如果端口仍在“使用”中,Windows 不会更新注册表,就像当程序拥有文件句柄时您无法删除文件一样。
如果您想测试设备是否被删除,可以使用 Window API 调用 (http://www.pinvoke.net/default.aspx/user32/RegisterDeviceNotification.html)。希望有帮助!
I'm assuming you mean System.IO.Ports.SerialPort.GetPortNames(), because i could not find a GetPortList() function anywhere. MSDN says: "If the registry contains stale or otherwise incorrect data then the GetPortNames method will return incorrect data", so that's probably where the problem lies. I guess Windows doesn't update the registry if the port is still being 'used', just like you can't delete a file when a program has a handle on it.
If you want to test if the device is removed, you can do so with a Window API call (http://www.pinvoke.net/default.aspx/user32/RegisterDeviceNotification.html). Hope that helps!
GetPortNames()
从注册表项读取端口是正确的。每次打开或关闭端口时,Windows 都会自动更新该注册表项。
但尽管如此,我还是遇到了这样的情况:注册表中列出了一个不存在的端口,并且也是从
GetPortNames()
返回的。当我尝试打开此端口时,我收到“端口 XYZ 不存在”。那是什么???
我现在找到原因了:
使用 www.sysinternals.com 中的 PortMon 后总会发生这种情况。
该工具存在缺陷,如果在监视端口时关闭端口,则死端口会在注册表中徘徊。
在这种情况下,唯一的补救措施是重新启动计算机。
It is correct that
GetPortNames()
reads the ports from the Registry keyThis is automagically updated by Windows every time a port is opened or closed.
But nevertheless it has happened to me that there is a non-existent Port listed in the Registry, and also returned from
GetPortNames()
. When I try to open this port I get "The Port XYZ does not exist".What is that ???
I now found out the reason:
This happens always after using PortMon from www.sysinternals.com.
This tool is buggy and lets the dead port hanging around in the Registry if the port is closed while it is monitored.
In this case the only remedy is to reboot the computer.
正如其他人所提到的,它是非常特定于驱动程序的。似乎没有办法使用 .Net API 检查 GetPortNames() 返回的端口是否确实存在并且有效。
至于为什么端口会这样,我发现一些USB转串口驱动程序会在端口突然拔出时导致应用程序崩溃。
其他驱动程序(通常是那些不会崩溃的驱动程序)会将端口保留在列表中,直到您的应用程序将其关闭,然后它就会消失。尝试读取或写入过时的端口(通常)会导致超时或错误。据推测,为了不使应用程序崩溃,驱动程序需要在旧端口在应用程序中仍处于打开状态时保留它。
如果您再次插入端口,某些驱动程序甚至能够将其重新连接到您的应用程序,而其他驱动程序将无法识别该端口,直到您的应用程序关闭旧端口。如果端口因为设备重新启动而消失,这种重新连接行为可能会有些危险,因为这样它会突然处于与应用程序预期不同的状态,而没有明显的迹象表明它已重置。至少如果您从端口收到错误,您就知道发生了一些事情。
我还发现,如果我忘记关闭端口,它不会从列表中消失,直到垃圾收集器开始处理 SerialPort 对象。
As others have mentioned, it's very driver-specific. There does not appear to be a way to check with the .Net API whether a port returned by GetPortNames() actually exists and is valid.
As for why the ports behave like this, I have found that some USB-to-serial drivers cause the application to crash when the port is unplugged suddenly.
Other drivers, often those that do not crash, will keep the port in the list until your application closes it, then it disappears. Trying to read from or write to the stale port will (usually) cause timeouts or errors. Presumably, in order not to crash the application, the driver needs to keep the stale port around while it is still open in the application.
If you plug in the port again, some drivers are even be able to reconnect it to your application, others will not recognize the port until your application closes the stale port. This reconnecting behaviour can be somewhat dangerous if the port disappeared because the device rebooted, because then it will suddenly be in a different state than your application expects without an obvious indication that it has reset. At least if you get errors from the port you know that something happened.
I've also found that if I forget to close the port, it won't disappear from the list until the garbage collector gets around to disposing the SerialPort object.