SerialPort.GetPortNames() behavior - c#

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?

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.

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!

It is correct that GetPortNames() reads the ports from the Registry key
HKLM\Hardware\DeviceMap\SerialComm
This 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.

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.

Related

c# SerialPort suddenly stops receiving data and unable to reopen

I have a curious problem that i cant make sense of.
Here the facts:
.net 5 Project published as arm32 linux self contained
Running on a Raspberry pi Compute module
in one case that we cant provoke at the moment, the serial port stops receiving data and sent data seems not to reach the target.
the described process runs 24/7 for month without error.
as a attempt to solve this we implemented a watchdog that tries to reinstanciate the SerialPort in this case. But it doesnt solve the problem. a connection to the Serial port can only be regained by restarting the process.
The serial port fir all properties looks open and alive, just with the caveat that data issnt received and sent.
i have no more idead how this problem happens and how to prevent it.

Get connected Port

I want to build a program that will run on my Raspberry Pi and starts processes when I connect to it. I want to run a specific processes if there is a connection on a specific port.
So I need to get the port somebody is trying to connect to.
For example:
If I open localhost:4444 in my browser I want to get 4444 as a string or an int.
It doesn’t need to be C#. Would be great, but it can also be in other languages.
Is this possible and how can I achieve that?
Listening for an incoming packet on any port number, rather than on a specific port number, is an unnatural act on Linux (the rPi's OS) and on most operating systems.
You could probably, with a lot of work, figure out how to do it with the tcpdump command line utility and/or its underlying libpcap runtime library. This subsystem intercepts network messages at the driver level and reports them. You could write a hunk of code that notices an incoming connection request and launches a server (written in your language of choice) to listen on that port.
But, the server would not be launched in time to handle the request detected by tcpdump or libpcap. Instead, the OS on the rPi would reject it immediately with the ECONNREFUSED OS error. You would have to rely on the client software retrying the connection after the rPi had a chance to launch the server. But client software like web browsers don't automatically retry those refused connections.
You might be able to make this work, but it will always be a brittle solution and a miserable hack. You will be better off rethinking this system design. You should run servers (listeners) on any ports you think your clients will use.
I must mention the security hazards of the approach you propose. A cybercreep could crash your machine simply by running nmap on it if you started servers upon receiving messages on random ports.

Bluetooth COM Port Exceptions in C#.Net

I am using Windows7 with 32feet.net libraries for the windows application development. I get the COM ports after I scan and pair the device. When I open the port and try to send the data in the COM port, I am getting two types of exceptions and they are given below
Error Code Exception
121 The semaphore timeout has expired
1168 Element not found.
I also tried with a workaround given in the below link,
http://zachsaw.blogspot.in/2010/07/serialport-ioexception-workaround-in-c.html
but nothing fruitful.
Lastly my suspicion revolves around the Bluetooth driver.
Any insights on how to find an approach for this exceptions.
Regards,
Gibson
I had simular issue with this. My issue was resolved with .net 4.7.1. Also I needed to make sure I had the latest microsoft bluetooth driver for the bluetooth device i was using
SerialPort streams no longer terminate the process when exceptions occur on the background thread. This can happen when removing a USB serial port while in use. This new behavior is controlled by the Switch.System.IO.Ports.DoNotCatchSerialStreamThreadExceptions AppContext switch. This switch is set to truetf get by default when targeting .NET 4.7 or below. [428461, System.dll, Bug]
https://github.com/Microsoft/dotnet/blob/0745983093568027ff931672d9db021e3e120b5b/releases/net471/dotnet471-changes.md
Update: Actually it appears to be 2 issues in one. .net bug and a firmware issue where the device was never turning back on the bluetooth module.
I used a RN-42 chip for Bluetooth operations and studied few things from the below link,
https://electronics.stackexchange.com/questions/38113/does-bluetooth-range-increase-with-lower-baud-rate
The culprit was the baud rate!!!!
I tried using the standard baud rate of 9600 but surprisingly some data transfers were proved to be successful, alas the COM port got disconnected despite the Bluetooth device state being connected to the windows application. During this state, the application threw exceptions after few data transfers like "Element not found" and " The semaphore timeout period has expired". Changing the baud rate suggested by the manufacturer seems to be more stable. Workaround : Align to the same baud rate in the windows application and the Bluetooth device.

Serial port does not receive data

first of all sorry for my english :)
I have a PCI serial ports card with 2 COM ports. I am using it to receive data from another computer via serial cables. (That other computer will be named as "Sender" subsequently)
The problem is, when cables are plugged in to my computer and i reboot (Windows 7),(Sender is still running...), then my PC does not receive any data. But when i reboot and after that I connect the cables in my PC it starts to receive. I temporary solved it by firstly starting my PC and then the Sender PC, but it's really a terrible solution...
I tried to connect my PC with a different computer (different sender), and it works good.
So I think that the problem can be with my main Sender. Maybe it is waiting for some signal from my computer that the ports are ready? Or Windows 7 can block my serial ports card (standard COM1 which is not on that card works fine) during reboot? Maybe I have to manually send some signal to Sender that I'm ready? By the way, I cannot, in any way, make adjustments to the Sender PC; only turn it on or off.
I do not have any expertise on serial ports so I really don't know what to do, or what I'm currently doing wrong.
Any ideas? (my receiver application is programmed in C#)
UPDATE: I forgot to mention that when the cables are connected... reboot... then ports can't be even opened.
This is a problem caused by the handshake signals. The Sender's DSR (Data Set Ready) is wired to your DTR (Data Terminal Ready). It will see the signal turn off when you reboot, now it gets sulky about sending anything because it thinks that you are no longer connected. You can exacerbate this problem by not setting the SerialPort.DtrEnable to true in your program, that's very commonly overlooked.
Same story with the RTS and CTS signals, if you set the SerialPort.Handshake property to anything else than Handshake.RequestToSend (the recommended value) then it now becomes your job to control the signal. You must set the RtsEnable property to true explicitly in your code.
It tends to work by accident, you're apt to use another program to test the connection. Like HyperTerminal or Putty, they'll turn the signals on for you and your program will now operate correctly.
This kind of bug could of course also exist in Sender. If you can't fix that code then all you can do is rewire the cable. Connect RTS to DSR and CTS on the Sender side to it will always see the signals turned on.
Problem was in card... I changed for new one and now its working correctly. Looks like the card was too old for Windows 7.

Getting info on USB-Serial converter

Hope you can help me on this.
I have a serial device, this device will then be connected to a USB-Serial converter, then the converter will be connected to my PC's usb port. The system will add another COM port to the Device Manager.
My question is, how can I possibly map the COM port number to the converter in C#? I can successfully enumerate available COM port in the system by doing the SerialPort.GetPortNames(), but not sure what COM port number this converter have.
thanks
ar
You can usually get some decent info out of a WMI query, although it requires the device driver to cooperate. Most do afaik. Run a query on the Win32_SerialPort class. You can use the WMI Code Creator tool to experiment with the query and auto-generate the C# code you need.
Don't count on being able to auto-select the device. You'll need a config option to allow the user to select the port. You can display the info you got from the query to help her pick the right one. Or ask her to unplug the device and plug it back in, the added COM port should be the right one.
We solved this different ways for different applications. We used explicit configuration for an instance where we had exactly one device of a particular type, but it wasn't clear what COM port it was going to be assigned until the system was configured. In another case, we had one USB cable that broke out into a hub with a bunch of converters on it, so we probed all the COM ports we could open successfully to look for our devices of interest.
A couple caveats with USB/serial converters on Windows -- if your device is something like a GPS unit that sends out data whenever it's powered on, Windows might detect it as an old serial mouse if it's plugged in during boot. Also, plugging into a different USB port is likely to chew up an additional COM port number (as well as break any explicit configuration you've done).
When i had the same problem (RFID reader), I checked each port if there was any data.
Probably it would be something in COM4 : COM9.
I know that it's not the best solution, but i used it on mobile device where i am sure about my COM connections...
Maybe in your driver's *.ini file there is some information about COM number.
If you are using an FTDI based solution for the USB<-> serial conversion, you can use the FT_PROG utility which is available from the FTDI web site to assign custom VID:PID pairs to the converter, which you can then query to identify which adapter is assigned to which virtual port.
Alternatively, you can make use of the FTDIChip-ID which is unique for each chip, details on this including code samples are located here: http://ftdichip.com/Support/SoftwareExamples/FTDIChip-ID.htm
You would have to look this up somewhere in the registry.
I can only assume this is a FTDI chip. If so, you may be able to get info from using their public API, which is included with the drivers.
If no other answers, I will check later tonite at home, as my JTAG debugger has the same chip.
Update:
Here is the registry key for my device's assigned COM port (under PortName)
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_0483&PID_5740\498C54823932\Device Parameters
I guess you can just enumerate thru the USB devices with the usbser driver.

Categories

Resources