C++ 如何检查 HANDLE 是否有效?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5603625/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check if a HANDLE is valid or not?
提问by losingsleeep
In C++, I have opened a serial port that has a HANDLE
. Since the port may close by an external application, how can I verify that the HANDLE
is still valid before reading data?
在 C++ 中,我打开了一个带有HANDLE
. 由于端口可能被外部应用程序关闭,我如何HANDLE
在读取数据之前验证它是否仍然有效?
I think it can be done by checking the HANDLE
against a suitable API function, but which?
Thank you.
我认为可以通过检查HANDLE
合适的 API 函数来完成,但是哪个?谢谢你。
采纳答案by janm
Checking to see whether a handle is "valid" is a mistake. You need to have a better way of dealing with this.
检查句柄是否“有效”是错误的。你需要有更好的方法来处理这个问题。
The problem is that once a handle has been closed, the same handle value can be generated by a new open of something different, and your test might say the handle is valid, but you are not operating on the file you think you are.
问题是一旦句柄被关闭,相同的句柄值可以通过不同的东西的新打开来生成,并且您的测试可能会说句柄是有效的,但您并没有对您认为的文件进行操作。
For example, consider this sequence:
例如,考虑这个序列:
- Handle is opened, actual value is 0x1234
- Handle is used and the value is passed around
- Handle is closed.
- Some other part of the program opens a file, gets handle value 0x1234
- The original handle value is "checked for validity", and passes.
- The handle is used, operating on the wrong file.
- 句柄打开,实际值为0x1234
- 使用句柄并传递值
- 把手关闭。
- 程序的其他部分打开一个文件,得到句柄值 0x1234
- 原始句柄值“检查有效性”,并通过。
- 使用了句柄,对错误的文件进行了操作。
So, if it is your process, you need to keep track of which handles are valid and which ones are not. If you got the handle from some other process, it will have been put into your process using DuplicateHandle(). In that case, you should manage the lifetime of the handle and the source process shouldn't do that for you. If your handles are being closed from another process, I assume that you are the one doing that, and you need to deal with the book keeping.
因此,如果是您的流程,则需要跟踪哪些句柄有效,哪些无效。如果您从某个其他进程获得句柄,它将使用 DuplicateHandle() 放入您的进程中。在这种情况下,您应该管理句柄的生命周期,而源进程不应该为您这样做。如果您的句柄正在被另一个进程关闭,我假设您就是这样做的人,并且您需要处理簿记。
回答by Krit
Some WinAPI functions return meaningless ERROR_INVALID_PARAMETER even if valid handles are passed to them, so there isa real use case to check handles for validity.
即使将有效句柄传递给某些 WinAPI 函数,它们也会返回无意义的 ERROR_INVALID_PARAMETER,因此有一个真实的用例来检查句柄的有效性。
GetHandleInformation function does the job: http://msdn.microsoft.com/en-us/library/ms724329%28v=vs.85%29.aspx
GetHandleInformation 函数完成这项工作:http: //msdn.microsoft.com/en-us/library/ms724329%28v=vs.85%29.aspx
回答by Hans Passant
as the port may close by a external application
因为端口可能会被外部应用程序关闭
This is not possible, an external application cannot obtain the proper handle value to pass to CloseHandle(). Once you have the port opened, any other process trying to get a handle to the port will get AccessDenied.
这是不可能的,外部应用程序无法获得传递给 CloseHandle() 的正确句柄值。一旦您打开了端口,任何其他试图获得该端口句柄的进程都将被拒绝访问。
That said, there's crapware out there that hacks around this restriction by having secret knowledge of the undocumented kernel structures that stores handles for a process. You are powerless against them, don't make the mistake of taking on this battle by doing the same. You will lose. If a customer complains about this then give them my doctor's advice: "if it hurts then don't do it".
也就是说,有一些垃圾软件通过对存储进程句柄的未记录内核结构的秘密知识来绕过此限制。你对他们无能为力,不要错误地采取同样的行动来参加这场战斗。你会输的。如果顾客对此抱怨,那么请给他们我的医生的建议:“如果它很痛,那就不要这样做”。
回答by Felix Dombek
If you are given a HANDLE
and simply want to find out whether it is indeed an open file handle, there is the Windows API function GetFileInformationByHandlefor that.
如果您得到一个HANDLE
并且只是想确定它是否确实是一个打开的文件句柄,则可以使用 Windows API 函数GetFileInformationByHandle。
Depending on the permissions your handle grants you for the file, you can also try to move the file pointer using SetFilePointer, read some data from it using ReadFile, or perform a null write operation using WriteFilewith nNumberOfBytesToWrite
set to 0.
根据你的手柄授予您该文件的权限,你也可以尝试使用移动文件指针SetFilePointer,利用从中读取一些数据的ReadFile,或执行使用空写操作的WriteFile与nNumberOfBytesToWrite
设置为0。
回答by RedX
Probably you are under windows and using ReadFile
to read the data. The only way to check it is trying to read. If the HANDLE
is invalid it'll return an error code (use GetLastEror() to see which one it is) which will probably be ERROR_HANDLE_INVALID
.
可能你在windows下,ReadFile
用来读取数据。检查它的唯一方法是尝试阅读。如果HANDLE
无效,它将返回一个错误代码(使用 GetLastEror() 来查看它是哪个),可能是ERROR_HANDLE_INVALID
.
回答by CompuPlanet
I know that it's a little bit late but I had a similar question to you, how to check if a pipe (a pipe I created using CreateFile) is still open (maybe the other end shut down the connection) and can read, and if it is not, to open it again. I did what @Felix Dombek suggested, and I used the WriteFile to check the connection. If it returned 1 it means the pipe is open, else I opened it using the CreateFile again. This implies that your pipe is duplex. Here's the CreateFile:hPipe2 = CreateFile(lpszPipename2, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
and here is how I checked for the connection:
我知道这有点晚了,但我有一个类似的问题给你,如何检查管道(我使用 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
}
This is working just fine for me :)
这对我来说很好用:)
回答by losingsleeep
In order to check the handle , first we need to know what is our HANDLE for, (for a File/Port/Window, ...), Then find an appropriate function to check it (thanks @janm for help). Note that the function's duty may be specially for this destination or not. In my case that iv'e opened a Serial port by CreateFile() , i can check the COM status by GetCommState() API function that fills our COM info struct. If the port is not open anymore or inaccessible the function returns 0 and if you call GetLastError() immediately, you`ll get the ERROR_INVALID_HANDLE value. Thanks everyone for helps.
为了检查句柄,首先我们需要知道我们的句柄是什么,(对于文件/端口/窗口,...),然后找到一个合适的函数来检查它(感谢@janm 的帮助)。请注意,该功能的职责可能是专门针对此目的地的,也可能不是。在我通过 CreateFile() 打开串行端口的情况下,我可以通过填充我们的 COM 信息结构的 GetCommState() API 函数检查 COM 状态。如果端口不再打开或不可访问,该函数返回 0,如果您立即调用 GetLastError(),您将获得 ERROR_INVALID_HANDLE 值。感谢大家的帮助。
回答by Codr
Try using the IsWindow()function ;-)
尝试使用IsWindow()函数;-)
IsWindow()is a function of the Windows API since Windows 2000.
IsWindow()是 Windows API 自 Windows 2000 以来的一个函数。