Как проверить, является ли РУЧКА действительной или нет? - PullRequest
18 голосов
/ 09 апреля 2011

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

Я думаю, что это можно сделать, сравнив HANDLE с подходящей функцией API, но какой? Спасибо.

Ответы [ 9 ]

18 голосов
/ 09 апреля 2011

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

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

Например, рассмотрим следующую последовательность:

  1. Ручка открыта, фактическое значение 0x1234
  2. Используется дескриптор, и значение передается вокруг
  3. Ручка закрыта.
  4. Какая-то другая часть программы открывает файл, получает значение дескриптора 0x1234
  5. Исходное значение дескриптора «проверяется на достоверность» и проходит.
  6. Используется дескриптор, работающий с неверным файлом.

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

7 голосов
/ 26 апреля 2012

Некоторые функции WinAPI возвращают бессмысленную ERROR_INVALID_PARAMETER, даже если им передаются действительные дескрипторы, поэтому существует реальный вариант использования для проверки дескрипторов на действительность.

Функция GetHandleInformation выполняет работу: http://msdn.microsoft.com/en-us/library/ms724329%28v=vs.85%29.aspx

5 голосов
/ 09 апреля 2011

как порт может закрываться внешним приложением

Это невозможно, внешнее приложение не может получить правильное значение дескриптора для передачи в CloseHandle (). После открытия порта любой другой процесс, пытающийся получить дескриптор порта, получит AccessDenied.

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

1 голос
/ 13 марта 2013

Если вы получили HANDLE и просто хотите узнать, действительно ли это дескриптор открытого файла, для этого есть функция Windows API GetFileInformationByHandle .

В зависимости от разрешений, которые ваш дескриптор предоставляет вам для файла, вы также можете попробовать переместить указатель файла с помощью SetFilePointer , прочитать некоторые данные из него с помощью ReadFile или выполнить нулевая операция записи с использованием WriteFile с nNumberOfBytesToWrite, установленным в 0.

1 голос
/ 09 апреля 2011

Возможно, вы находитесь под Windows и используете ReadFile для чтения данных.Единственный способ проверить это - попытаться прочитать.Если HANDLE недопустимо, он вернет код ошибки (используйте GetLastEror (), чтобы увидеть, какой это), который, вероятно, будет ERROR_HANDLE_INVALID.

0 голосов
/ 20 ноября 2017

Konuyla ilgili örnek `

// File handle: CreateFile(), GetHandleInformation() and CloseHandle()
#include <windows.h>
#include <stdio.h>

int main(void)
{
// handle to a file
HANDLE hFile;
// file and path, change accordingly. LPCWSTR is a pointer to a constant
// null-terminated string of 16-bit Unicode characters. It is a typedef:
// typedef CONST WCHAR *LPCWSTR. The modifier 'L' is for wide character.
LPCWSTR fname = L"c:\\testfile.txt";
DWORD lpdwFlags[100];
BOOL test;

// Create a file with the given information...
hFile = CreateFile(fname, // file to be opened
GENERIC_WRITE, // open for writing
FILE_SHARE_WRITE, // share for writing
NULL, // default security
CREATE_ALWAYS, // create new file only
FILE_ATTRIBUTE_NORMAL |FILE_ATTRIBUTE_ARCHIVE | SECURITY_IMPERSONATION,
// normal file archive and impersonate client
NULL); // no attr. template

if(hFile == INVALID_HANDLE_VALUE)
printf("Could not open %s file, error %d\n", fname, GetLastError());
else
{
printf("File's HANDLE is OK!\n");
test = GetHandleInformation(hFile, lpdwFlags);
printf("The return value is %d, error %d\n", test, GetLastError());
}
// when finished, close the file handle
CloseHandle(hFile);
DeleteFile(fname);
return 0;
}`

от http://www.tenouk.com/cpluscodesnippet/createfilegetclosehandleinfo.html

0 голосов
/ 26 февраля 2015

Я знаю, что уже немного поздно, но у меня был похожий вопрос к вам, как проверить, открыт ли канал (канал, который я создал с помощью CreateFile) (возможно, другой конец закрыл соединение) и может прочитать и, если это не так, чтобы открыть его снова. Я сделал то, что предложил @Felix Dombek, и я использовал WriteFile, чтобы проверить соединение. Если он вернул 1, это означает, что канал открыт, иначе я снова открыл его, используя CreateFile. Это подразумевает, что ваша труба дуплексная. Вот CreateFile:
hPipe2 = CreateFile(lpszPipename2, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
и вот как я проверил соединение:

while(1)
{   
    bool MessageSent = WriteFile(hPipe2, "Test", 0, &cbWritten, NULL);
    if (!(MessageSent))
    {
        LogsOut("Read pipe has been disconnected");
        //Call method to start the pipe again
        break;
    }
    Sleep(200); // I need this because it is a thread
}

У меня это прекрасно работает :) 1007 *

0 голосов
/ 08 января 2013

Попробуйте использовать функцию IsWindow () ; -)

IsWindow () является функцией Windows API начиная с Windows 2000.

0 голосов
/ 09 апреля 2011

Чтобы проверить дескриптор, сначала нам нужно узнать, для чего нужна наша РУЧКА (для файла / порта / окна, ...), затем найти подходящую функцию для ее проверки (спасибо @janm за помощь) , Обратите внимание, что функция функции может быть специально для этого места назначения или нет. В моем случае, когда я открыл последовательный порт с помощью CreateFile (), я могу проверить состояние COM с помощью функции API GetCommState (), которая заполняет нашу структуру информации COM. Если порт больше не открыт или недоступен, функция возвращает 0, и если вы немедленно вызовите GetLastError (), вы получите значение ERROR_INVALID_HANDLE. Спасибо всем за помощь.

...