jcurl / RJCP.DLL.SerialPortStream

SerialPortStream is an independent implementation of System.IO.Ports.SerialPort and SerialStream for better reliability and maintainability. Default branch is 2.x and now has support for Mono with help of a C library.
Microsoft Public License
639 stars 199 forks source link

Access Denied: COM4 #11

Closed davidbitton closed 8 years ago

davidbitton commented 8 years ago

I'm receiving an UnauthorizedAccessException when calling Open(). The port can be opened by other apps. This is Windows 10, VS 2k15 and .net 4.6. Thanks.

    public async Task<MspResponse> SendMessage(MspCodes mspCodes, byte[] data = null) {

        var signal = new SemaphoreSlim(0, 1);
        var response = new MspResponse(MspCodes.MSP_API_VERSION);

        using (var serialPortStream = new SerialPortStream(PortName, BaudRate)) {
            serialPortStream.WriteTimeout = 100;
            serialPortStream.ReadTimeout = 100;

            serialPortStream.DataReceived += (sender, args) => {
                try {
                    var sps = sender as SerialPortStream;
                    if (sps == null) return;

                    var readBuffer = new byte[sps.BytesToRead];
                    sps.Read(readBuffer, 0, readBuffer.Length);
                    if (sps.IsOpen) sps.Close();
                    response = DeserializeMessage(readBuffer);
                } finally {
                    signal.Release();
                }
            };

            try {
                if (!serialPortStream.IsOpen)
                    serialPortStream.Open();
            } catch (UnauthorizedAccessException exception) {
                Debug.WriteLine(exception.Message);
                throw;
            }

            var request = new MspRequest(mspCodes, data);
            var buffer = SerializeMessage(request);
            serialPortStream.Write(buffer, 0, buffer.Length);

            await signal.WaitAsync(10000);
        }

        return response;
    }
davidbitton commented 8 years ago

I tried OpenDirect() but that failed the same way too.

jcurl commented 8 years ago

without a stacktrace to say where it's failing exactly, I'm guessing it's failing here (WinNativeSerial.cs).

    public void Open()
    {
        ...
        m_ComPortHandle = UnsafeNativeMethods.CreateFile(@"\\.\" + PortName,
            NativeMethods.FileAccess.GENERIC_READ | NativeMethods.FileAccess.GENERIC_WRITE,
            NativeMethods.FileShare.FILE_SHARE_NONE,
            IntPtr.Zero,
            NativeMethods.CreationDisposition.OPEN_EXISTING,
            NativeMethods.FileAttributes.FILE_FLAG_OVERLAPPED,
            IntPtr.Zero);
        if (m_ComPortHandle.IsInvalid) WinIOError();

where WinIOError is seeing from the OS error 5.

What software are you using to open your COM port? What driver is your COM port? Are you sure that you don't have another program which is opening it already, that will also lead to an authorization error.

I'm using my library regularly on Windows 10 1607, VS2015 with .NET 4.6.x, as well as Windows 7 SP1 x64, .NET 4.6 and have never observed this problem when using com0com, 16550A, FTDI, PL2303RA, PL2303H

davidbitton commented 8 years ago

I'm fairly certain I do not have anything else open. I opened the COM port using Advanced Serial Data Logger. I was able to open the port from my code using System.IO.Ports. Here is the stack trace from the exception:

   at RJCP.IO.Ports.Native.WinNativeSerial.WinIOError()
   at RJCP.IO.Ports.Native.WinNativeSerial.Open()
   at RJCP.IO.Ports.SerialPortStream.Open(Boolean setCommState)
   at RJCP.IO.Ports.SerialPortStream.OpenDirect()
   at appname.Services.SerialService.<SendMessage>d__8.MoveNext() in X:\appname\appname\Services\SerialService.cs:line 55

This is the driver info for the Port.

drivers

Thanks!

jcurl commented 8 years ago

Well, at least it's easy to see where and the OS is reporting the error. I'm downloading dotPeek to look at the MS sources on how it opens the COM port. I might not have time to investigate until end of next week.

If you're happy with modifying the sources, you could try different parameters to the CreateFile method. For curiosity, as you're using a COM4, if you can modify the sources, what happens if you remove the ".\" at the front?

davidbitton commented 8 years ago

Don't know. I'll have to pull it out as a Nuget package and add your project into the solution. I'll let you know.

jcurl commented 8 years ago

Did a quick look at the reference sources using dotpeek, this is what MS does:

        SafeFileHandle tempHandle = UnsafeNativeMethods.CreateFile("\\\\.\\" + portName,
            NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE,
            0,    // comm devices must be opened w/exclusive-access
            IntPtr.Zero, // no security attributes
            UnsafeNativeMethods.OPEN_EXISTING, // comm devices must use OPEN_EXISTING
            flags,
            IntPtr.Zero  // hTemplate must be NULL for comm devices
            );

Weird, it looks almost identical. NativeMethods.FileShare.FILE_SHARE_NONE has a value of 0.

        int flags = UnsafeNativeMethods.FILE_FLAG_OVERLAPPED;
        // disable async on win9x
        if (Environment.OSVersion.Platform == PlatformID.Win32Windows) {
            flags = UnsafeNativeMethods.FILE_ATTRIBUTE_NORMAL;
            isAsync = false;
        }

Mine is overlapped. So it doesn't look different at all (and I don't support Win9x)

So based on the preanalysis, I have no idea why SerialPort.Open() works, but mine doesn't, as the semantics are the same.

jcurl commented 8 years ago

Is there any new information? I can't explain why you see this error, particularly when the code from MS and my code are identical at the point where the serial port is opened.

davidbitton commented 8 years ago

Some other code had the port locked up. Whoops.

On Thu, Oct 13, 2016 at 3:36 PM Jason Curl notifications@github.com wrote:

Is there any new information? I can't explain why you see this error, particularly when the code from MS and my code are identical at the point where the serial port is opened.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/jcurl/SerialPortStream/issues/11#issuecomment-253615791, or mute the thread https://github.com/notifications/unsubscribe-auth/AAQ61-UiMiw4W3NfvON3VaVY12KtRcLTks5qzog0gaJpZM4KIHdN .

David B. Bitton Code No Evil, LLC Code Made Fresh Daily