Unhandled Com port Exception?

Sam Tal 21 Reputation points
2021-09-26T08:14:58.453+00:00

In VS2019 community on Win10/64 I have a Com port with wich my c# program excange serial data.
The same port can be opened by another application on the same computer.
When the port is opend by the other app and I try to access the port from my current app, I (expectedly) receive an exception message.
The message is of type: System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.
and the inner exception is: UnauthorizedAccessException: Access to the port 'COM6' is denied..
So far so god.
The problem is that I can not handle that (or any other relevant) exception. With any exception catch I still get the message and the program halts to be restarted.
I have tried the general exception handler and all relevant (as is indicated by the documentation) exceptions and placed a break in each handler, for no avail. The program still halts at the same exception message.

Here is what I have tried (each with a break):
catch (Exception ex)
catch (System.Reflection.TargetInvocationException portInUse)
catch (UnauthorizedAccessException portInUse)
catch (InvalidOperationException portInUse)
catch (FormatException
catch (System.ArgumentOutOfRangeException)

This is the full call stack message:
This exception was originally thrown at this call stack:
System.IO.Ports.InternalResources.WinIOError(int, string)
System.IO.Ports.SerialStream.SerialStream(string, int, System.IO.Ports.Parity, int, System.IO.Ports.StopBits, int, int, System.IO.Ports.Handshake, bool, bool, bool, byte)
System.IO.Ports.SerialPort.Open()
Lift_Motor_Control.Main.btnSend_Click(object, System.EventArgs) in Main.cs
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Thx

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,323 questions
{count} votes

Accepted answer
  1. AgaveJoe 26,151 Reputation points
    2021-09-30T12:56:46.013+00:00

    Below is the basic test I recommended above. I'm using an FTDI chipset and the D2XX driver.

    First, run application 1

    namespace SerialPortConsole
    {
        class Program
        {
            static SerialPort _serialPort;
    
            static void Main(string[] args)
            {
    
                _serialPort = new SerialPort("COM3", 9600);
                _serialPort.Open();
    
                Console.WriteLine("Close Post? (y/n) ");
                string val = Console.ReadLine();
    
                if(val == "y")
                {
                    _serialPort.Close();
                }
    
            }
        }
    }
    

    Next, run application 2 which tries to open the same serial port, "COM3", that application 1 has open.

    namespace SerialPortopenTest
    {
        class Program
        {
            static SerialPort _serialPort;
            static void Main(string[] args)
            {
                try
                {   
                    _serialPort = new SerialPort("COM3", 9600);
                    Console.WriteLine($"IsOpen: {_serialPort.IsOpen}");
                    _serialPort.Open();
                    Console.WriteLine($"IsOpen: {_serialPort.IsOpen}");
                    _serialPort.Close();
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }
    }
    

    The results are:

    IsOpen: False
    Access to the port 'COM3' is denied.

    These are the expected results as explained in the SerialPort.IsOpen documentation. The IsOpen property belongs to the current SerialPort instance. The property does not verify if the port is open by another application.

    It is up to you to write proper exception handlers and logic flow to handle this situation. A standard try...catch works great. For example...

        class Program
        {
            static SerialPort _serialPort;
            static void Main(string[] args)
            {
                string userInput = "y";
                while (userInput == "y")
                {
                    try
                    {
                        _serialPort = new SerialPort("COM3", 9600);
                        Console.WriteLine($"IsOpen: {_serialPort.IsOpen}");
                        _serialPort.Open();
                        Console.WriteLine($"IsOpen: {_serialPort.IsOpen}");
                        _serialPort.Close();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
    
                        Console.WriteLine("Try closing the application that has the port open.  Do you want to try opening COM3 at 9600 Baud again (y/n)? ");
                        userInput = Console.ReadLine();
    
                        if(userInput == "n")
                        {
                            break;
                        }
                    }
                }
                Console.WriteLine("Goodbye");
            }
        }
    

2 additional answers

Sort by: Most helpful
  1. Sam Tal 21 Reputation points
    2021-09-27T09:21:57.013+00:00

    Some code example of the above, (stripped off irrelevant lines)

    public Class1()
        {
        }
        public bool writeDataPort(string msg)
        {
            switch (CurrentTransmissionType)
            {
                case TransmissionType.Text:
                    try
                    {
                        if (!(comPort.IsOpen == true))
                        {
                            comPort.Open();
                        }
                        comPort.Write(msg);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }
                    break;
    
                case TransmissionType.Hex:
                    try
                    {
                        byte[] HexMsg = HexToByte(msg);
                        if (comPort.IsOpen == false) { comPort.Open(); }
                        if (HexMsg != null) comPort.Write(HexMsg, 0, HexMsg.Length);
                        return true;
                    }
                    catch (FormatException ex)
                    {
                        DisplayData(MessageType.Error, ex.Message + "\n");   //Could not find any recognizable 
                    }
                    catch (Exception ex)
                    {
                        DisplayData(MessageType.Error, ex.Message + "\n");
                    }
                    break;
                default:
                    if (comPort.IsOpen == false)
                    {
                        comPort.Open();
                    }
                    comPort.Write(msg);
                    DisplayData(MessageType.Outgoing, msg + "\n");
                    return true;
            }
            return true;
        }
    

  2. AgaveJoe 26,151 Reputation points
    2021-09-28T14:39:43.523+00:00

    The SerialPort.IsOpen properties does not check if another application has the port open. See the SerialPort.IsOpen reference documentation..

    I suspect there are other issues with the code base that we cannot see. The code you've share has unknown and questionable logic. What happens if DisplayData() throws an exception? How does the caller handle exceptions? The way the code is written, writeSerialData() expects to always return true. That seems a little odd.

    You can clean up the code a bit. For example, SerialPort.IsOpen is true or false. Rather than...

    if (comPort.IsOpen == false) { comPort.Open(); }  
    

    You can write the following which is easier to read => if not comport is open then open the com port.

    if (!comPort.IsOpen) { comPort.Open(); }  
    

    A string is already a byte array already. What exactly does HexToByte() do?

    The default switch does not have an exception handler. Is the default branch executing?

    After reviewing the code above I suspect there are other issues with the code base. I recommend creating two test projects. The first project opens the COM port. The second project tries to open the same port. Verify if you are able to catch and handle the exception in the second application. If the exception handler catches the exception then you have logical bug(s) and need to do a bit more troubleshooting.