Click here to Skip to main content
15,879,326 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Here is some code which simply opens a com port and should allow me to do things with it, however it does not because the COM port returns with "Access Denied" as you can see I am trying to do everything to clear up that message for the next run in order to free up the port to no avail. The port remains frozen if some error occurs.... any idea how to free up a port, restart it or something in order to regain access to the port after an error has occurred without needing to unplug, replug it? thanks for your help!


C++
DCB dcb;
    b->h1 = CreateFile(b->port,GENERIC_READ | GENERIC_WRITE,
    0,    // comm devices must be opened w/exclusive-access
    NULL, // no security attributes
    OPEN_EXISTING, // comm devices must use OPEN_EXISTING
    0,    // overlapped I/O
    NULL);



if (b->h1 == INVALID_HANDLE_VALUE)
    {
        //Major Error Need to Prepare for next run & Exit with error
        //Clear Comm Error Flag and also reset for I/O
        DWORD MsgID = GetLastError();
        char *TextSize;
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, MsgID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &TextSize, 0, 0);

        DWORD dwErrorFlags;
        COMSTAT ComStat;
        int result;
        BOOL fSuccess2;

        ClearCommError(b->h1, &dwErrorFlags, &ComStat );
        ClearCommBreak(b->h1);

        //  Fill in some DCB values and set the com state:
        //  57,600 bps, 8 data bits, no parity, and 1 stop bit.
        dcb.BaudRate = b->boud;     // set the baud rate
        dcb.ByteSize = 8;             // data size, xmit, and rcv
        dcb.Parity = NOPARITY;        // no parity bit
        dcb.StopBits = ONESTOPBIT;    // one stop bit
        SetCommState(b->h1, &dcb);
        //Port is still open so try to restart the comm port with those new settings above.
        fSuccess2 = SetCommState(b->h1, &dcb);
        //Do a complete purge of the comm now.
        PurgeComm(b->h1, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
        //Now Close Port
        CloseHandle(b->h1);
        b->h1 = NULL;
        b = NULL;
        a = NULL;
        hSock = NULL;
        hSock2 = NULL;
        ComSock.Close();
        ClosePort();

        return 2;

    }


[EDIT Jochen Arndt: Copied from solution]

The idea is to be able to "Force" close the port, the problem is another thread may have the port open and I want to close it, without having access to the other instance that encountered an error.

For example, someone might pull out the chord during transmission, if we encounter the error, now we want to clear up the port, so everything would be fine on the next run, I am specifically interested in these functions as they seem to help with this process but they didnt do much to resolve the "Access Denied" error:

C++
ClearCommError(b->h1, &dwErrorFlags, &ComStat );
ClearCommBreak(b->h1);
PurgeComm(b->h1, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);


Another option I looked at while investigating was the use of DevCon.exe which is not what I am looking for, I am specifically looking to restart the com port using code, not plugging in & unplugging the device, etc....

Thanks for your help & advice!
Posted
Updated 13-Nov-19 6:35am
v2
Comments
[no name] 17-Feb-15 4:09am    
The whole thing does not make any sense. if (b->h1 == INVALID_HANDLE_VALUE) is unequivocal and you keep trying to do operations on b->h1? No point trying to close an invalid handle. Start again and write some pseudocode first.
Jochen Arndt 17-Feb-15 4:24am    
You should edit your question using the green 'Improve question' link rather than putting additional information into a solution. I have copied the text for you.

I suggest to delete your solution before it is automatically deleted when others report it as 'Not a solution'.

I will also update my answer.
Shirzad Sharif 17-Feb-15 4:27am    
good idea, I am new here, thanks! :)
Shirzad Sharif 17-Feb-15 4:26am    
Makes sense, however I would think that the whole purpose of this function: ClearCommError(b->h1, &dwErrorFlags, &ComStat ); is to get the broken handle and clear the error, normally I would just end the if statement with the FormatMessage line, but I want to clear the error first...
[no name] 17-Feb-15 5:01am    
You can clear errors that occur on a valid handle. In this case you don't get a valid handle at all. Assuming the thread that held a valid handle is under your control that is where you have to clean up.

1 solution

On Windows serial ports can be only opened by one instance at time. If you try to open a serial port that is already opened, you will get an access denied error.

To avoid this error, the port must be closed by the instance that has it opened.

Your above code snippet makes no sense. The return value INVALID_HANDLE_VALUE is an error indicator and can't be used as handle argument to API functions.

[UPDATE]
You can't close a serial port that is opened by another application.

But you can handle errors like unplugging the chord in your application.
If the chord is unplugged, there is no need to call other API functions than CloseHandle.

Some hints for applications using a serial port:

Implement an application global variable for the port handle (may be stored as member of a serial port class).

Initialize the variable with INVALID_HANDLE_VALUE to indicate that the port is not opened.

Assign the handle when openening the port.

When the connection is lost (unplugged or device powered off), close the port and set the handle back to INVALID_HANDLE_VALUE.

With communications errors you can try to recover (ClearCommError, PurgeComm). If this fails you may force a re-opening by closing and opening.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900