2
votes

I'm getting tired of fighting this every so often. PCs in question are industrial touchscreen models that should never change. This one is Windows 10 while I believe it has also happened on Windows 7. While in the past sometimes this error dealt with emulated com ports (i.e., USB connector) in this case it is a true com port so I can't just plug it into another one since I'm using both 232 connectors. The PC will work fine for months and then one day something goes amiss with a COM port and I'll have to shuffle them around, trying to figure out which ones work now. This is a major pain when I must do it remotely (1000 miles away) with a tech sometimes having to plug cables into different positions.

To eliminate anything with my original program, I have created a very simple test app as follows:

Imports System.IO.Ports

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load

        Try
            Dim tempList As List(Of String) = SerialPort.GetPortNames.ToList
            ListBox1.DataSource = tempList

        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim tempPort As New SerialPort
        tempPort.PortName = "COM1"

        Try
            tempPort.Close()

        Catch ex As Exception
            MessageBox.Show("Closing error: " & ex.ToString)
        End Try

        Try
            tempPort.Open()
            MessageBox.Show("COM1 Opened")

        Catch ex As Exception
            MessageBox.Show("Open error: " & ex.ToString)
        End Try

    End Sub
End Class

Even after a fresh reboot, I get no error on the Close attempt but the traditional access denied when I attempt to open it. It does show up in ListBox1, of course.

System.UnauthorizedAccessException: Access to the port 'COM1' is denied. at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str) 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()

Touchscreens are always supposed to be on COM4 and when I look at the provided config utility that is what always shows up. Going into Device Manager shows no conflicts that I can see on IRQ or memory location for COM1. What is preventing this little test app from opening the port on this PC after a reboot?!?!?

UPDATE: For now at least, it magically "fixed" itself somehow (my bet is gremlins). After a couple more hours of research I remoted back in to see if a reboot into Safe Mode would help and lo and behold my normal program was running! WTH?!?!? I asked the tech what he did to fix it, and he thought I had done something to fix it. Argh!!! I still need to find an answer so a production PC isn't down for 16 hours the next time this happens while we beat our heads against the wall.

2
See Hans Passant's answers here and hereHebeleHododo
@HebeleHododo I've seen those before but don't see how either is relevant in this case.topshot
Proper advice just hasn't much to do with what's on topic here, talk to your supervisor about it. Just protect yourself against the so common mistake a tech will make next when he starts tinkering with the hardware. In VB.NET use Project > Properties > Application tab > tick the "Make single instance application" checkbox.Hans Passant
@HansPassant I always check that box for my apps unless I really do want multiple copies running which I think has been only once. These techs won't tinker with PC hardware unless I tell them to. Any issue at all and they call me to figure out what is wrong.topshot

2 Answers

1
votes

You are probably getting that exception because you are not waiting after closing the port.

From SerialPort.Close documentation

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.

Unfortunately, there is no way to know how long you need to wait. You could start with 100 ms and go your way up. If it wouldn't bother user, I would go with 500 ms to be safe.

Ideally, you would Open the port once and Close when your program closes.

0
votes

Not really an answer (yet at least), but next the time this happens, aside from trying Safe Mode, I'll try finding a serial handle using Process Explorer as detailed in this thread. That seems promising.

UPDATE (Apr 10 '17) - finally found the issue thanks to Clone's answer (not the accepted one) in this thread. Windows sometimes identifies devices with a constant data stream connected to a serial port as a serial mouse (e.g., Microsoft Serial Ballpoint), and tries to install them, TAKING CONTROL OVER THE PORT WITHOUT ANY PROCESS USING IT. Indeed, Process Explorer could not see anything using COM1. The solution is to DISABLE (not uninstall) the device using Device Manager under Mice And Other Pointing Devices.