I have written a Windows forms program in Visual studio 2015 Community that lists all devices with serial capabilities, like serial ports, arduino boards, USB-to serial converters, Bluetooth serial, virtual ports, etc. in a listbox.
There is also a Button that closes previous selected and opens selected port.
In my program my Arduino NANO clone shows as: USB-SERIAL CH340:COM6 and my Bluetooth LE device as:[BLE05]:COM14
Here is a Dropbox link to download the solution:
Also on Github:
You can use it in your own program or change it as You wish.
If You do not have Visual studio 2015, You can browse the files and copy code in Your own code editor.
The example is spiked with comments so beginners can understand what is going on.
Greets,
I've never seen SerialPort.GetPortNames() return an empty list when an Arduino is plugged into my (or any other) computer. That reeks of a driver issue, a bad cable, or some other un-good thing.
I'll take this opportunity to mention that the .NET SerialPort class is buggy as all hell, and one of the reasons I prefer... cough clone cough boards (like the Waveshare Uno Plus) with FT232s on them for applications where the Arduino is paired with a Windows app. Then you can use FTDI's FT_PROG tool to flash a name onto your Arduino, and use their D2XX API (which has a nice C# wrapper available) to open the device by name. No legacy serial headaches!
But if you're determined to go the legacy serial route, I'd vote for one of the following options:
Do SerialPort.GetPortNames() (which should work fine unless something's messed up) and just use the result to populate a drop-down menu. Then allow the user to pick the COM port. Any mistakes are on them at that point.
OR... Devise a data stream format that includes an identifier for your device. Open and read a little from each of the COM ports returned by GetPortNames(), looking for your identifier. Optionally have a brief conversation with your device to prove you've found it.
SerialPort is a major reliability headache, though. Things like surprise-removing your device while SerialPort is reading it will damage the internal state of the object in ways that you, the consumer, can't detect (the non-managed stream object gets freed), and afterwards you're holding a ticking time bomb. The most common symptom is that your app crashes on close because the garbage collector tries to re-free the stream (this issue has been know for years and not fixed by Microsoft). There are all kinds of embarrassing workarounds, like calling GC.SuppressFinalize() on the stream members, which seems to work...mostly. But again, I find that the reliable thing is just to avoid legacy COM altogether. The AVR USB is great for debugging, but it becomes onerous after that. IMO.
PaulS:
You have some proof of that? I have NEVER had an issue with it. I do a LOT of network apps at work and at home.
Yeah. The most obnoxious of these are (IMO) the IOException-on-Close() bug, and the ObjectDisposedException bug. Both are blogged about extensively and widely reported on many forums, including Microsoft's own forums. Here are a couple of useful blogs with suggested workarounds:
Here's a good blog with some suggestions for a number of other SerialPort bugs/design flaws, although the thrust of the blog is really, "stay away from this class":
Not exactly encouraging!
So there are a few. Other sharp edges include the need to sleep between Close() and Open() on the same object or with the same port, and the fact that calling Close() from a UI thread on shutdown can lead to a deadlock. The former is actually called out in the documentation, although it's embarrassing vague:
Microsoft:
"The best practice for any application is to wait for some amount of time after calling the Close method before attempting to call the Open method, as the port may not be closed instantly."
(Not surprisingly, when you look at SerialPort code others have written, you'll see that everybody picks a different amount of time. )
In short: It's difficult to use SerialPort well, and even using it well doesn't guarantee success. There are reliability issues that require the consumer to implement silly workarounds like inhibiting garbage collection. They haven't been fixed by Microsoft, nor have any of the workarounds been officially blessed (as far as I can tell). Mostly I suspect Microsoft just doesn't have a lot of time to devote to improving legacy serial support.
After wrestling with the above issues, as well as wrestling with the general annoyance of having my Windows app try to figure out what COM port my Arduino was plugged into, I realized that wresting with legacy serial just wasn't necessary. It's so easy not to, in fact. Just get any clone with an FT232 on it and use the D2XX C# wrapper FTDI provides. Then you can flash proper names/descriptions onto your devices and enumerate/open them by name. After you've gone there, you'll never want to mess with SerialPort and its myriad headaches again.