Shirzad Sharif Ответов: 1

Как восстановить доступ к COM-порту после отказа в доступе?


Вот некоторый код, который просто открывает com-порт и должен позволить мне делать с ним что-то, однако это не так, потому что COM-порт возвращается с "отказано в доступе", как вы можете видеть, я пытаюсь сделать все, чтобы очистить это сообщение для следующего запуска, чтобы освободить порт безрезультатно. Порт остается замороженным, если происходит какая-то ошибка ... есть идеи, как освободить порт, перезапустить его или что-то еще, чтобы восстановить доступ к порту после того, как произошла ошибка, без необходимости отключать его, снова подключать? спасибо за вашу помощь!


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: скопировано из решения]

Идея состоит в том, чтобы иметь возможность "принудительно" закрыть порт, проблема в том, что другой поток может иметь открытый порт, и я хочу закрыть его, не имея доступа к другому экземпляру, который столкнулся с ошибкой.

Например, кто-то может вытащить аккорд во время передачи, если мы столкнемся с ошибкой, теперь мы хотим очистить порт, чтобы все было хорошо при следующем запуске, я особенно заинтересован в этих функциях, так как они, кажется, помогают в этом процессе, но они не сделали много для устранения ошибки "отказано в доступе".:

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


Еще одним вариантом, который я рассматривал во время расследования, было использование DevCon.exe это не то, что я ищу, я специально ищу, чтобы перезапустить com-порт с помощью кода, а не подключать и отключать устройство и т. д....

Спасибо за вашу помощь и советы!

[no name]

Все это не имеет никакого смысла. если (b->h1 == INVALID_HANDLE_VALUE) является однозначным, и вы продолжаете пытаться выполнять операции над b->h1? Нет смысла пытаться закрыть недопустимый дескриптор. Начните снова и сначала напишите какой-нибудь псевдокод.

Jochen Arndt

Вы должны отредактировать свой вопрос, используя зеленую ссылку "улучшить вопрос", а не добавлять дополнительную информацию в решение. Я скопировал текст для вас.

Я предлагаю удалить ваше решение до того, как оно будет автоматически удалено, когда другие сообщат о нем как о "не решении".

Я также обновлю свой ответ.

Shirzad Sharif

хорошая идея, я здесь новичок, спасибо! :)

Shirzad Sharif

Имеет смысл, однако я думаю, что вся цель этой функции: ClearCommError(b->h1, &dwErrorFlags, &ComStat ); состоит в том, чтобы получить сломанный дескриптор и очистить ошибку, обычно я просто заканчиваю оператор if строкой FormatMessage, но сначала я хочу очистить ошибку...

[no name]

Вы можете очистить ошибки, возникающие на допустимом дескрипторе. В этом случае вы вообще не получаете действительного дескриптора. Предполагая, что поток, который содержал допустимый дескриптор, находится под вашим контролем, вот где вы должны очистить.

Shirzad Sharif

очень хорошая мысль... спасибо!

1 Ответов

Рейтинг:
10

Jochen Arndt

В Windows последовательные порты могут быть открыты только одним экземпляром одновременно. Если вы попытаетесь открыть уже открытый последовательный порт, то получите сообщение об ошибке отказа в доступе.

Чтобы избежать этой ошибки, порт должен быть закрыт экземпляром, который его открыл.

Приведенный выше фрагмент кода не имеет никакого смысла. Значение INVALID_HANDLE_VALUE является индикатором ошибок и не может использоваться в качестве аргумента дескриптора для функций API.

[ОБНОВЛЕНИЕ]
Вы не можете закрыть последовательный порт, открытый другим приложением.

Но вы можете справиться с такими ошибками, как отключение аккорда в вашем приложении.
Если аккорд отключен, нет необходимости вызывать другие функции API, кроме CloseHandle.

Некоторые советы для приложений, использующих последовательный порт:

Реализуйте глобальную переменную приложения для дескриптора порта (может храниться как член класса последовательного порта).

Инициализируйте переменную с помощью INVALID_HANDLE_VALUE чтобы указать, что порт не открыт.

Назначьте дескриптор при открытии порта.

Когда соединение потеряно (отключено или устройство выключено), закройте порт и установите ручку обратно в положение INVALID_HANDLE_VALUE.

С ошибками связи вы можете попытаться восстановить (ClearCommError, PurgeCommЕсли это не удается, вы можете принудительно открыть снова, закрывая и открывая.