如何检查HANDLE是否有效?

时间:2011-04-09 07:45:07

标签: c++ c winapi port handle

在C ++中,我打开了一个HANDLE的串口。由于端口可能被外部应用程序关闭,如何在读取数据之前验证HANDLE是否仍然有效?

我认为可以通过针对合适的API函数检查HANDLE来完成,但是哪个? 谢谢。

10 个答案:

答案 0 :(得分:17)

检查手柄是否“有效”是一个错误。你需要有一个更好的方法来解决这个问题。

问题是,一旦句柄被关闭,可以通过新打开不同的东西生成相同的句柄值,并且您的测试可能会说句柄有效,但您没有对您认为的文件进行操作是

例如,请考虑以下序列:

  1. 处理打开,实际值为0x1234
  2. 使用句柄,值传递
  3. 句柄已关闭。
  4. 程序的其他部分打开一个文件,获取句柄值0x1234
  5. 原始句柄值“已检查有效性”,并通过。
  6. 使用句柄,在错误的文件上操作。
  7. 因此,如果是您的过程,则需要跟踪哪些句柄有效以及哪些句柄无效。如果你从其他进程获得了句柄,那么它将使用DuplicateHandle()进入你的进程。在这种情况下,您应该管理句柄的生命周期,源进程不应该为您执行此操作。如果您的句柄被另一个进程关闭,我认为您是那样做的,并且您需要处理簿记。

答案 1 :(得分:7)

有些WinAPI函数返回无意义的ERROR_INVALID_PARAMETER,即使有效的句柄传递给它们,所以一个真实的用例来检查句柄的有效性。

GetHandleInformation函数完成工作: http://msdn.microsoft.com/en-us/library/ms724329%28v=vs.85%29.aspx

答案 2 :(得分:5)

  

因为端口可能被外部应用程序关闭

这是不可能的,外部应用程序无法获取传递给CloseHandle()的正确句柄值。打开端口后,尝试获取端口句柄的任何其他进程都将获得AccessDenied。

也就是说,那里的crapware通过秘密了解存储进程句柄的未记录内核结构来解决这一限制。你对他们无能为力,不要错误地做同样的战斗。你会输的。如果客户抱怨这个,那就告诉他们医生的建议:“如果疼,那就不要这样做。”

答案 3 :(得分:1)

可能你在windows下并使用ReadFile来读取数据。检查它的唯一方法是尝试阅读。如果HANDLE无效,它将返回错误代码(使用GetLastEror()查看它是哪一个),这可能是ERROR_HANDLE_INVALID

答案 4 :(得分:1)

如果给你一个HANDLE并且只是想知道它是否确实是一个打开的文件句柄,那么就有Windows API函数GetFileInformationByHandle

根据您的句柄授予您文件的权限,您还可以尝试使用SetFilePointer移动文件指针,使用ReadFile从中读取一些数据,或使用句柄执行空写操作将nNumberOfBytesToWrite设置为0的WriteFile

答案 5 :(得分:0)

尝试使用IsWindow()功能; - )

IsWindow()是自Windows 2000以来Windows API的一个功能。

答案 6 :(得分:0)

我知道它有点迟了但是我有一个类似的问题,如何检查管道(我使用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
}

这对我来说很好用:):

答案 7 :(得分:0)

Konuylailgiliö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

答案 8 :(得分:0)

您可以使用 DuplicateHandle 来测试句柄有效性。

第一种方法:您可以尝试复制要检查有效性的句柄。基本上,无效句柄不能复制。

第二种方法:DuplicateHandle 函数确实从一开始就在 Win32 句柄描述符表中搜索空记录以重用它,并为它分配一个重复的句柄。您可以在大于您的句柄地址的值上测试重复的句柄地址值,如果它更大,则句柄不会被视为无效,因此不会被重用。但是这个方法是非常具体和有限的,它只在你要测试的句柄值地址上方没有空的或无效的句柄记录时才有效。

但是,只有在您跟踪所有句柄创建和复制的情况下,上述所有内容才有效。

答案 9 :(得分:-1)

为了检查句柄,首先我们需要知道我们的HANDLE是什么(对于文件/端口/窗口,......),然后找一个合适的函数来检查它(感谢@janm的帮助) 。请注意,该功能的职责可能是专门针对此目的地的。在我的情况下,iv'e通过CreateFile()打开一个串口,我可以通过填充我们的COM信息结构的GetCommState()API函数检查COM状态。如果端口不再打开或无法访问,则函数返回0,如果立即调用GetLastError(),则会获得ERROR_INVALID_HANDLE值。谢谢大家的帮助。