3

I'm trying to open and read from a serial port using the System.IO.Ports.SerialPort class. I dragged the serial port from the tool pane (Visual Studio 2008) on to my Windows Forms application.

I've got a property grid set up so I can easily change properties of the serial port at runtime. When I try to open the port, I get the error shown below. I don't understand why because I can open and read from the port using Hyperterminal.

Any ideas?

System.IO.IOException Error connection: A device attached to the system is not functioning
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.InternalResources.WinIOError()
   at System.IO.Ports.SerialStream.set_DtrEnable(Boolean value)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at Test.CardReader.frmMain.Connect() in D:\Develop\2.0\Projects\Kiosk\EmbeddedBrowser\Windows Forms\Test.CardReader\Form1.cs:line 166

Note, this is a USB connection, so it's actually a virtual serial port.

My settings are as follows:

BaudRate = 9600
DataBits = 8
DiscardNull = false
DtrEnable = false
Handshake = None
Parity = None
ParityReplace = 63
PortName = COM3
ReadBufferSize = 4096
ReadTimeout = -1
ReceivedBytes = 1
TrsEnable = False
StopBits = One
WriteBufferSize = 2048
WriteTimeout = -1

I downloaded PortMon from Sysinternals. I've captured two logs. The first is the log how what happens when HyperTerminal opens the port, and the second is what happens when the .NET SerialPort class tries to open the port:

HyperTerminal:

IRP_MJ_CREATE                  USBSER000  SUCCESS       Options: Open
IOCTL_SERIAL_SET_QUEUE_SIZE    USBSER000  SUCCESS       InSize: 8192 OutSize: 8192
IOCTL_SERIAL_CONFIG_SIZE       USBSER000  SUCCESS       Size: 0
IOCTL_SERIAL_GET_BAUD_RATE     USBSER000  SUCCESS
IOCTL_SERIAL_GET_LINE_CONTROL  USBSER000  SUCCESS
IOCTL_SERIAL_GET_CHARS         USBSER000  SUCCESS
IOCTL_SERIAL_GET_HANDFLOW      USBSER000  SUCCESS
IOCTL_SERIAL_GET_BAUD_RATE     USBSER000  SUCCESS
IOCTL_SERIAL_GET_LINE_CONTROL  USBSER000  SUCCESS
IOCTL_SERIAL_GET_CHARS         USBSER000  SUCCESS
IOCTL_SERIAL_GET_HANDFLOW      USBSER000  SUCCESS
IOCTL_SERIAL_SET_BAUD_RATE     USBSER000  SUCCESS       Rate: 9600
IOCTL_SERIAL_SET_RTS           USBSER000  SUCCESS
IOCTL_SERIAL_SET_DTR           USBSER000  * 0xC0000001
IOCTL_SERIAL_SET_LINE_CONTROL  USBSER000  SUCCESS       StopBits: 1 Parity: NONE WordLength: 8
IOCTL_SERIAL_SET_CHAR          USBSER000  SUCCESS       EOF:1a ERR:0 BRK:0 EVT:1a XON:f6 XOFF:6
IOCTL_SERIAL_SET_HANDFLOW      USBSER000  SUCCESS       Shake:80000001 Replace:80000040 XonLimit:80 XoffLimit:200
IOCTL_SERIAL_SET_TIMEOUTS      USBSER000  SUCCESS       RI:10 RM:0 RC:0 WM:0 WC:5000
IOCTL_SERIAL_SET_WAIT_MASK     USBSER000  SUCCESS       Mask: RLSD ERR
IOCTL_SERIAL_GET_MODEMSTATUS   USBSER000  SUCCESS
IOCTL_SERIAL_WAIT_ON_MASK      USBSER000
IRP_MJ_READ    USBSER000                                Length 80

.NET SerialPort:

IRP_MJ_CREATE                  USBSER000  SUCCESS       Options: Open
IOCTL_SERIAL_GET_PROPERTIES    USBSER000  SUCCESS
IOCTL_SERIAL_GET_MODEMSTATUS   USBSER000  SUCCESS
IOCTL_SERIAL_GET_BAUD_RATE     USBSER000  SUCCESS
IOCTL_SERIAL_GET_LINE_CONTROL  USBSER000  SUCCESS
IOCTL_SERIAL_GET_CHARS         USBSER000  SUCCESS
IOCTL_SERIAL_GET_HANDFLOW      USBSER000  SUCCESS
IOCTL_SERIAL_GET_BAUD_RATE     USBSER000  SUCCESS
IOCTL_SERIAL_GET_LINE_CONTROL  USBSER000  SUCCESS
IOCTL_SERIAL_GET_CHARS         USBSER000  SUCCESS
IOCTL_SERIAL_GET_HANDFLOW      USBSER000  SUCCESS
IOCTL_SERIAL_SET_BAUD_RATE     USBSER000  SUCCESS       Rate: 9600
IOCTL_SERIAL_CLR_RTS           USBSER000  SUCCESS
IOCTL_SERIAL_CLR_DTR           USBSER000  * 0xC0000001
IOCTL_SERIAL_SET_LINE_CONTROL  USBSER000  SUCCESS       StopBits: 1 Parity: NONE WordLength: 8
IOCTL_SERIAL_SET_CHAR          USBSER000  SUCCESS       EOF:1a ERR:0 BRK:0 EVT:1a XON:11 XOFF:13
IOCTL_SERIAL_SET_HANDFLOW      USBSER000  SUCCESS       Shake:0 Replace:0 XonLimit:4096 XoffLimit:4096
IOCTL_SERIAL_GET_BAUD_RATE     USBSER000  SUCCESS
IOCTL_SERIAL_GET_LINE_CONTROL  USBSER000  SUCCESS
IOCTL_SERIAL_GET_CHARS         USBSER000  SUCCESS
IOCTL_SERIAL_GET_HANDFLOW      USBSER000  SUCCESS
IOCTL_SERIAL_SET_BAUD_RATE     USBSER000  SUCCESS       Rate: 9600
IOCTL_SERIAL_CLR_RTS           USBSER000  SUCCESS
IOCTL_SERIAL_CLR_DTR           USBSER000  * 0xC0000001
IOCTL_SERIAL_SET_LINE_CONTROL  USBSER000  SUCCESS       StopBits: 1 Parity: NONE WordLength: 8
IOCTL_SERIAL_SET_CHAR          USBSER000  SUCCESS       EOF:1a ERR:0 BRK:0 EVT:1a XON:11 XOFF:13
IOCTL_SERIAL_SET_HANDFLOW      USBSER000  SUCCESS       Shake:0 Replace:0 XonLimit:4096 XoffLimit:4096
IOCTL_SERIAL_CLR_DTR           USBSER000  * 0xC0000001
IRP_MJ_CLEANUP                 USBSER000  SUCCESS
IRP_MJ_CLOSE                   USBSER000  SUCCESS
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jeremy
  • 44,950
  • 68
  • 206
  • 332
  • Does the InnerException of the IOException have any more details? Also, can you open this in HyperTerminal (or another terminal)? – Jon B Jan 30 '09 at 18:07
  • @Jon B, There is no inner exception in this error, and it does work in hyperterminal. – Jeremy Jan 30 '09 at 18:58
  • In the Win32 API, DTR is controlled by one of the flags in the `DCB` structure: http://msdn.microsoft.com/en-us/library/aa363436(VS.85).aspx – ChrisW Jan 30 '09 at 22:51
  • @Jeremy Did you ever fix this problem? I know this was a while ago now, but I am facing [the same problem](http://stackoverflow.com/questions/14885288/io-exception-error-when-using-serialport-open) with subtle differences. – tmwoods Mar 12 '13 at 19:41
  • I used a 3rd party component called OpenNETCF.IO.Serial.dll. Works very well. – Jeremy Mar 12 '13 at 22:35

5 Answers5

4

Regarding the differences between HyperTerminal and the .NET serial port object, HyperTerminal is a commercial, stable application. If the underlying serial port object died or threw an exception, HyperTerminal hid it from you. The .NET serial port object throws more exceptions than any other .NET object I've used.

Points to make:

  • Whenever you change a setting, close it first, change it, then re-open it. Some ports really hate it when you change it while open.
  • Expect to do a lot of 'try-catch's around your serial port object, around every thing you do.
  • Make sure you have one for each possible exception listed, and make sure each one checks the message (it can be different under different circumstances). Many are recoverable simply by closing and reopening.
  • Try following exactly where the exceptions are being thrown. See if modifying the order you set things fixes it ... the object is really finicky.

If you've tried explicitly setting DTR to false before opening, then you may just have to grin and bear it with that device. The SerialPort object is not one of the glowing examples of a well implemented library in .NET. If you notice, HyperTerminal gets that same error, but it just ignores it.

If you can, try it with a regular serial port or a different brand USB device. If you still get the same error, it might be something on your application side.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Robert P
  • 15,707
  • 10
  • 68
  • 112
  • I'm calling the Open method. the exception is being thrown somewhere in there. I used PortMonitor from sysinternals and found that under the hood, IOCTL_SERIAL_CLR_DTR is being issued which returns an error of 0xC0000001 and causes the SerialPort class to close the port and throw an exception. – Jeremy Jan 30 '09 at 23:25
  • Hyperterminal does not cause an IOCTL_SERIAL_CLR_DTR to be issued. Not sure how to suppress it in the .net framework. – Jeremy Jan 30 '09 at 23:25
  • Sadly, you may *not* be able to do anything about that. :/ – Robert P Feb 02 '09 at 16:50
1

In a real UART, DTREnable will assert the DTR pin of your UART to indicate you are ready to receive data.

Depending on your driver's implementation, you may need to set DTREnable to true to open the port.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Quassnoi
  • 413,100
  • 91
  • 616
  • 614
  • Yes, I forgot to mention, it is a USB connection, so it's a virtual serial port. If what you're suggestng is the problem how can I work around it? The serial port is st to DtrEnable = false – Jeremy Jan 30 '09 at 17:45
  • This fixed my problem using the port, simple _Port.DtrEnable=true; – Aaron Aug 12 '10 at 02:39
0

It looks like the difference is the handshaking.

I haven't had problems with the serialport class and have written applications that ran at 800,000 bit/s.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
dbasnett
  • 11,334
  • 2
  • 25
  • 33
0

I had issue with the listener of serial port, the main process get's stuck - since it is sync. process, got solved by creating a thread and a timer

try
            {
                if (_serialConnection.IsOpen) _serialConnection.Close();
                _serialConnection.Open();
                Thread newThread = new Thread((obj) =>
                {
                    System.Timers.Timer timer = new System.Timers.Timer();
                    timer.Interval = 1000;
                    timer.Elapsed += (sender, e) =>
                    {
                        _slave.Listen();
                    };
                    timer.Enabled = true;
                    timer.Start();
                    
                });
                newThread.IsBackground = true;
                newThread.Start();
            }
            catch (Exception ex)
            {
                throw ex;
            }
Nada N. Hantouli
  • 1,310
  • 1
  • 12
  • 20
-1

See this forum post. I suspect it has to do with the hardware or the driver malfunctioning. This doesn't explain why it works with HyperTerminal though. Follow the advice from Joseph M. Newcomer to see what HyperTerminal is doing differently.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kgiannakakis
  • 103,016
  • 27
  • 158
  • 194
  • Hyperterminal isn't necessarily using the .NET class: it's using the Win32 API ... and it may be using less of the Win32 API, and/or have different error-handling, that the .Net class'. In particular, with the Win32 API you can open a port *and* subsequently fail to set some of its settings. – ChrisW Jan 30 '09 at 21:35
  • I ran th PortMon software from sysinternals, and added the logs to my question, I just don't know which win32 command now is causing the error, how how to get arround it. Is there a better serial port class available? – Jeremy Jan 30 '09 at 22:07
  • I think an expanded summary from that forum post would be in order (so this answer is self-contained - instead of sort of link-only). – Peter Mortensen Dec 18 '19 at 22:32