第二次调用 GetStdHandle 返回“无效”句柄。处理
我试图将控制台的文本颜色设置为给定颜色,打印一行(或多行),然后将颜色方案更改回原来的颜色。这就是我所拥有的:
Function SetConsoleTextColor(NewColor As UInt16) As UInt16
Declare Function SetConsoleTextAttribute Lib "Kernel32" (hConsole As Integer, attribs As UInt16) As Boolean
Declare Function GetStdHandle Lib "Kernel32" (hIOStreamType As Integer) As Integer
Declare Function GetConsoleScreenBufferInfo Lib "Kernel32" (hConsole As Integer, ByRef buffinfo As CONSOLE_SCREEN_BUFFER_INFO) As Boolean
Declare Sub CloseHandle Lib "Kernel32" (HWND As Integer)
Const STD_OUTPUT_HANDLE = -12
Dim conHandle As Integer = GetStdHandle(STD_OUTPUT_HANDLE)
Dim buffInfo As CONSOLE_SCREEN_BUFFER_INFO //A structure defined elsewhere
If GetConsoleScreenBufferInfo(conHandle, buffInfo) Then
Call SetConsoleTextAttribute(conHandle, NewColor)
CloseHandle(conHandle)
Return buffInfo.Attribute
Else
Return 0
End If
End Function
这在第一次调用时效果很好。控制台上新输出的文本颜色已更改,并返回以前的属性。但是,当我第二次调用此函数来重置属性时,GetStdHandle
返回一个与上次调用相同的句柄,但该句柄现在无效(因为我关闭了它)。
当然,这会导致错误,当我尝试使用手柄时。如果我将 conHandle 设为静态变量,并且仅在 conHandle 等于零(新数字变量的默认值)时才调用 GetStdHandle,则它可以正常工作。 RealBasic。)
我总是被告知要自己清理。我应该让这个手柄保持打开状态吗?
I'm trying to set the text color of a console to a given color, print one line (or more) and then change the color scheme back to what it was. Here's what I have:
Function SetConsoleTextColor(NewColor As UInt16) As UInt16
Declare Function SetConsoleTextAttribute Lib "Kernel32" (hConsole As Integer, attribs As UInt16) As Boolean
Declare Function GetStdHandle Lib "Kernel32" (hIOStreamType As Integer) As Integer
Declare Function GetConsoleScreenBufferInfo Lib "Kernel32" (hConsole As Integer, ByRef buffinfo As CONSOLE_SCREEN_BUFFER_INFO) As Boolean
Declare Sub CloseHandle Lib "Kernel32" (HWND As Integer)
Const STD_OUTPUT_HANDLE = -12
Dim conHandle As Integer = GetStdHandle(STD_OUTPUT_HANDLE)
Dim buffInfo As CONSOLE_SCREEN_BUFFER_INFO //A structure defined elsewhere
If GetConsoleScreenBufferInfo(conHandle, buffInfo) Then
Call SetConsoleTextAttribute(conHandle, NewColor)
CloseHandle(conHandle)
Return buffInfo.Attribute
Else
Return 0
End If
End Function
This works just fine on the first call. The text color for new output on the console is changed and the previous attributes are returned. However, when I call this a second time to reset the attributes GetStdHandle
returns a handle identical to the previous call, but which is now invalid (since I closed it.)
This causes an error, of course, when I try to use the handle. It works properly if I make conHandle
a static variable and only call GetStdHandle
if conHandle
is equal to zero (the default value for new numeric variable in RealBasic.)
I was always told to clean up after myself. Am I supposed to leave this handle open?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,您应该让手柄保持打开状态。
当您的进程退出时,该句柄会自动关闭。
Yes you are supposed to leave the handle open.
This handle is closed automatically when your process exits.
通过对各个站点进行研究,发现当您对 GetStdHandle 返回的句柄使用 CloseHandle 时,可能会发生不好的事情。很多时候,人们的回答似乎是,因为它获取了一个句柄而不是创建了一个句柄(因为函数名称中是 Get,而不是 Create),所以很明显它会获取一个由系统创建的句柄,并且关闭这个是一个坏主意。然而,实际的答案并不是那么明显(遗憾的是)。虽然 GetStdHandle 确实如此,但并非每个与句柄相关的 Get 函数实际上都能获取现有句柄。有些会创建新的句柄。例如,GetDC 实际上创建了一个设备上下文的新句柄,并且由于它是一个新句柄,因此必须使用 CloseHandle 正确关闭它。与某些人的回复不同,没有规定如果函数包含“Create”一词,则它会创建一个新句柄,而如果包含“Get”一词,则仅引用系统已创建的句柄。根本没有这样的规则。那么你怎么知道什么时候确实需要关闭句柄呢?一种方法是,如果 MSDN 没有明确声明需要在某个函数返回的句柄上使用 CloseHandle,那么可以安全地假设您不应该在该句柄上使用 CloseHandle。另一种解决方法是通过反复试验。如果使用 CloseHandle 导致您的程序出现更多错误,则不要使用 CloseHandle。如果不使用 CloseHandle 会导致您的程序出现更多错误,那么请使用 CloseHandle。我经常结合使用这些方法。如果遵循 MSDN 文档后我的程序似乎有错误,但以不同于 MSDN 指定的方式进行操作往往会减少程序中的错误,那么我会按照我通过反复试验确定的有效方法进行操作。
From doing research on various sites, it appears bad things can happen when you use CloseHandle on a handle returned by GetStdHandle. Often times, it seems that people's reply is that because it gets a handle rather than creating one (as the word Get, not Create, is in the function name) it should be obvious that it gets a handle created by the system, and that closing this is a bad idea. However, the actual answer is NOT this obvious (sadly). While it is true with GetStdHandle, not every Get function relating to handles actually gets an existing handle. Some create new handles. For example, GetDC actually creates a new handle to a device context, and as it is a new handle it must be properly closed with CloseHandle. Unlike some people's replies, there is no rule that if the function contains the word Create it creates a new handle, while if it contains the word Get it only references a handle already created by the system. There is no such rule at all. How do you know when a handle actually needs to be closed then? One way is that if MSDN doesn't specifically state that CloseHandle needs to be used on a handle returned by such-and-such function, then it is safe to assume that you should NOT use CloseHandle on that handle. Another way to figure it out is by trial and error. If using CloseHandle causes your program to have more bugs, then DON'T use CloseHandle. If NOT using CloseHandle causes your program to have more bugs, then USE CloseHandle. I often use a combination of these approaches. If after following the MSDN documentation my program seems to have bugs, but doing it differently than specified by MSDN tends to reduce the bugs in my program, I go by what I've determined works via trial-and-error.