I am looking for a way to have as much control as it is possible over serial port in my c# application. The problem is that I need to communicate with a device that has no documentation except for an old c++ program written to control it. I've tried to use SerialPort class to communicate with the device but its behaviour is quite odd (I have to repeat some of the commands, some other commands dont work at all). I would like to copy that unmanaged program's behaviour, however it开发者_如何学Go seems to be impossible with serialport class, as it does not provide access to low-level functions and structures like DCB for example.
Are there any low-level wrappers for serial communication available for .net? Maybe i could use reflection to manipulate serialport innacessible members at runtime?
For those suggesting to look at the .NET SerialPort class; frequent Stack Overflow answer provider on Serial related issues, Ben Voigt, provides some excellent insights on why a wrapper around WinAPI would eventually turn out to be a much better idea than using the framework provided SerialPort:
Ben Voigt on .NET SerialPort
A must read.
He also refers to a WinAPI wrapper that he might reveal in future blog posts. If that would happen, it would answer the original question.
Also, there seems to be at least one commercial solution providing the requested functionality here.
Another edit:
Some more searching online has yielded this blog post apparently from the time when there was no SerialPort class in .NET... Source code is provided showing how to wrap Win32 API for the purpose.
EDIT
Some users have pointed out that the above mentioned MSDN blog post link is dead.
The title of the linked article was:
"Use P/Invoke to Develop a .NET Base Class Library for Serial Device Communications", written by John Hind andpublished October 2002 as I can tell from another MSDN article referring to it:
Unfortunately, Microsoft seems to only serve editions of their magazine down to 2003:
FWIW, I found a half working online version elsewhere...
Unfortunetely, the SerialPort class is an incomplete wrapper. I have found the only way to gain access to the underlying DCB is through reflection.
The only other option would be to re-write SerialPort and make it complete. I have not seen any such implementation freely available (yet).
Here is an example where I used reflection to gain access to RTS_CONTROL_TOGGLE: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/45a89532-b01c-4ef8-aa46-532882cec004
The SerialPort class is a very thin wrapper around the Win32 serial port API, hard to see how another wrapper could improve your life. There are wrappers available from the .NET 1.x days, it didn't support serial ports. Here is one from MSDN magazine.
But you're just as likely to have the same problems. One way that written commands could get lost is by the device throwing away received bytes (or losing them) when it has turned off the RTS signal off. You fix that by setting the Handshake property to RequestToSend.
One way that things can go wrong with reading commands is to get the Read() call wrong. It will return an arbitrary number of bytes, as many as are available in the receive buffer. Pay attention to the return value, it tells you how many bytes were actually read. The only guarantee is that it will at least be 1 and never more than count.
The SysInternals' PortMon utility can help you troubleshoot communications, it gives you a raw view of what the device driver sees. Compare with, say, Hyperterminal or another known-good program.
Working with a serial port through PInvoke works fine. We're doing this in a Silverlight application, but it should work the same in a normal .NET app. The answer to Serial Communication with Silverlight 5 (COM port) provides a basic wrapper for a which could easily be adapted to your needs. It uses the normal WinAPI method so you get full access to all serial port functionality, like you would in a C++ application.
P.S. If you don't already, use PortMon to monitor what's happening on the line.
You may be able to copy the old C++ code into a managed C++ class, which you could then use just like any normal .NET class from your C# code. This may be the fastest way to reach your goal.
精彩评论