web-dev-qa-db-de.com

Wie überprüfe ich, ob ein HANDLE gültig ist oder nicht?

In C++ habe ich eine serielle Schnittstelle geöffnet, die eine HANDLE enthält. Wie kann ich überprüfen, ob die HANDLE noch gültig ist, bevor Daten gelesen werden, da der Port möglicherweise von einer externen Anwendung geschlossen wird?

Ich denke, es kann getan werden, indem die HANDLE mit einer geeigneten API-Funktion verglichen wird, aber welche? Vielen Dank.

18
losingsleeep

Das Überprüfen, ob ein Handle "gültig" ist, ist ein Fehler. Sie müssen einen besseren Weg finden, damit umzugehen.

Das Problem ist, dass nach dem Schließen eines Handles derselbe Handle-Wert durch ein neues Öffnen eines anderen Objekts generiert werden kann und Ihr Test möglicherweise sagt, dass das Handle gültig ist, aber Sie arbeiten nicht mit der Datei, die Sie für richtig halten.

Betrachten Sie zum Beispiel diese Reihenfolge:

  1. Handle ist geöffnet, der Istwert ist 0x1234
  2. Handle wird verwendet und der Wert wird weitergegeben
  3. Griff ist geschlossen.
  4. Ein anderer Teil des Programms öffnet eine Datei und erhält den Handle-Wert 0x1234
  5. Der ursprüngliche Handle-Wert wird "auf Gültigkeit geprüft" und besteht.
  6. Das Handle wird verwendet, um die falsche Datei zu bearbeiten.

Wenn es Ihr Prozess ist, müssen Sie also nachverfolgen, welche Handles gültig sind und welche nicht. Wenn Sie das Handle von einem anderen Prozess erhalten haben, wurde es mit DuplicateHandle () in Ihren Prozess eingefügt. In diesem Fall sollten Sie die Lebensdauer des Handles verwalten, und der Quellprozess sollte dies nicht für Sie tun. Wenn Ihre Handles von einem anderen Prozess geschlossen werden, gehe ich davon aus, dass Sie derjenige sind, der das tut, und Sie müssen sich mit der Buchhaltung befassen.

17
janm

Einige WinAPI-Funktionen geben den sinnlosen Wert ERROR_INVALID_PARAMETER zurück, auch wenn gültige Handles an sie übergeben werden. Daher ist vorhanden ein echter Anwendungsfall, um Handles auf Gültigkeit zu prüfen.

Die GetHandleInformation-Funktion erledigt den Job: http://msdn.Microsoft.com/en-us/library/ms724329%28v=vs.85%29.aspx

6
Krit

da der Port durch eine externe Anwendung geschlossen werden kann

Dies ist nicht möglich, eine externe Anwendung kann nicht den richtigen Handle-Wert erhalten, der an CloseHandle () übergeben wird. Sobald Sie den Port geöffnet haben, erhält jeder andere Prozess, der versucht, einen Handle für den Port zu erhalten, AccessDenied.

Das heißt, es gibt Crapware, die diese Einschränkung hackt, indem sie geheimes Wissen über die undokumentierten Kernelstrukturen besitzt, in denen Handles für einen Prozess gespeichert werden. Sie sind machtlos gegen sie, machen Sie nicht den Fehler, diesen Kampf anzunehmen, indem Sie dasselbe tun. Du wirst verlieren. Wenn sich ein Kunde darüber beschwert, geben Sie ihm den Rat meines Arztes: "Wenn es weh tut, dann tun Sie es nicht".

5
Hans Passant

Wenn Sie eine HANDLE erhalten und einfach herausfinden möchten, ob es sich tatsächlich um eine offene Datei handelt, gibt es die Windows-API-Funktion GetFileInformationByHandle .

Abhängig von den Berechtigungen, die Ihnen Ihr Handle für die Datei erteilt, können Sie auch versuchen, den Dateizeiger mit SetFilePointer zu verschieben, einige Daten mit ReadFile lesen oder einen Schreibvorgang mit WriteFile ausführen mit nNumberOfBytesToWrite auf 0 gesetzt.

1
Felix Dombek

Wahrscheinlich befinden Sie sich unter Windows und verwenden ReadFile zum Lesen der Daten. Die einzige Möglichkeit, dies zu überprüfen, ist das Lesen. Wenn HANDLE ungültig ist, wird ein Fehlercode zurückgegeben (verwenden Sie GetLastEror (), um zu sehen, welcher es ist), der wahrscheinlich ERROR_HANDLE_INVALID ist.

1
RedX

Versuchen Sie es mit der IsWindow () Funktion ;-)

IsWindow () ist eine Funktion der Windows API seit Windows 2000.

0
Codr

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;
}`

von http://www.tenouk.com/cpluscodesnippet/createfilegetclosehandleinfo.html

0
İbrahim Doğan

Ich weiß, dass es ein bisschen spät ist, aber ich hatte eine ähnliche Frage wie Sie, um zu überprüfen, ob eine Pipe (eine Pipe, die ich mit CreateFile erstellt habe) noch offen ist (vielleicht hat das andere Ende die Verbindung geschlossen) und lesen kann, und ob es ist nicht, es wieder zu öffnen. Ich habe das getan, was @Felix Dombek vorgeschlagen hat, und ich habe die Verbindung mit WriteFile überprüft. Wenn 1 zurückgegeben wird, bedeutet dies, dass die Pipe geöffnet ist, ansonsten habe ich sie erneut mit CreateFile geöffnet. Dies impliziert, dass Ihre Pipe Duplex ist. Hier ist die CreateFile:
hPipe2 = CreateFile(lpszPipename2, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
und so habe ich nach der Verbindung gesucht:

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
}

Das funktioniert gut für mich :)

0
CompuPlanet