Как проверить правильность РУЧКИ?
В С++ я открыл последовательный порт с HANDLE
. Поскольку порт может закрываться внешним приложением, как я могу проверить, что значение HANDLE
все еще действует до чтения данных?
Я думаю, что это можно сделать, проверив HANDLE
против подходящей функции API, но что?
Спасибо.
Ответы
Ответ 1
Проверка, является ли дескриптор "действительным", является ошибкой. Вам нужно иметь лучший способ справиться с этим.
Проблема заключается в том, что после того, как дескриптор закрыт, одно и то же значение дескриптора может быть сгенерировано новым открытием чего-то другого, и ваш тест может сказать, что дескриптор действителен, но вы не работаете с файлом, который, как вы думаете, есть.
Например, рассмотрим следующую последовательность:
- Ручка открыта, фактическое значение - 0x1234
- Используется дескриптор и значение передается
- Ручка закрыта.
- Другая часть программы открывает файл, получает значение дескриптора 0x1234
- Исходное значение дескриптора "проверено на достоверность" и проходит.
- Используется дескриптор, работающий с неправильным файлом.
Итак, если это ваш процесс, вам нужно отслеживать, какие дескрипторы действительны, а какие нет. Если вы получили ручку от какого-либо другого процесса, она будет перенесена в ваш процесс с помощью DuplicateHandle(). В этом случае вы должны управлять временем жизни дескриптора, и исходный процесс не должен делать этого для вас. Если ваши ручки закрыты от другого процесса, я предполагаю, что вы тот, кто это делает, и вам нужно иметь дело с книжным хранением.
Ответ 2
Некоторые функции WinAPI возвращают бессмысленный ERROR_INVALID_PARAMETER, даже если для них передаются действительные дескрипторы, поэтому есть реальный прецедент для проверки правильности дескрипторов.
Функция GetHandleInformation выполняет задание:
http://msdn.microsoft.com/en-us/library/ms724329%28v=vs.85%29.aspx
Ответ 3
поскольку порт может закрываться внешним приложением
Это невозможно, внешнее приложение не может получить правильное значение дескриптора для перехода к CloseHandle(). После открытия порта любой другой процесс, пытающийся получить дескриптор порта, получит AccessDenied.
Тем не менее, там, там, где есть обложки, которые обманывают это ограничение, имея секретные знания о недокументированных структурах ядра, которые хранят дескрипторы для процесса. Вы бессильны против них, не делайте ошибку, принимая эту битву, делая то же самое. Ты проиграешь. Если клиент жалуется на это, то дайте им совет моего врача: "Если это больно, тогда не делайте этого".
Ответ 4
Возможно, вы находитесь под окнами и используете ReadFile
для чтения данных. Единственный способ проверить это пытается прочитать. Если HANDLE
недействителен, он вернет код ошибки (используйте GetLastEror(), чтобы увидеть, какой из них он), который, вероятно, будет ERROR_HANDLE_INVALID
.
Ответ 5
Попробуйте использовать функцию IsWindow(); -)
IsWindow() является функцией Windows API с Windows 2000.
Ответ 6
Если вам дана HANDLE
и просто хотите выяснить, действительно ли это дескриптор открытого файла, есть функция Windows API GetFileInformationByHandle для этого.
В зависимости от разрешений, которые ваш дескриптор предоставляет вам для файла, вы также можете попытаться переместить указатель файла с помощью SetFilePointer, прочитать некоторые данные из он использует ReadFile или выполняет операцию нулевой записи, используя WriteFile с nNumberOfBytesToWrite
установлено значение 0.
Ответ 7
Я знаю, что это немного поздно, но у меня был схожий вопрос с вами, как проверить, что канал (канал, который я создал с помощью CreateFile) все еще открыт (возможно, другой конец отключает соединение) и может читать, а если нет, открыть его снова. Я сделал то, что предложил @Феликс Домбек, и я использовал 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
}
Это работает отлично для меня:)
Ответ 8
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 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
Ответ 9
Чтобы проверить дескриптор, сначала нам нужно знать, что такое наша РУЧКА, (для файла/порта/окна...), Затем найдите соответствующую функцию для проверки (спасибо @janm за помощь), Обратите внимание, что функция назначения может быть специально для этого пункта назначения или нет. В моем случае, когда iv'e открыл Serial порт CreateFile(), я могу проверить статус COM с помощью функции API GetCommState(), которая заполняет нашу структуру информации COM. Если порт больше не открыт или недоступен, функция возвращает 0, и если вы немедленно вызываете GetLastError(), вы получите значение ERROR_INVALID_HANDLE. Спасибо всем за помощь.