无法获得 AllocConsole 的 STD 句柄
Cannot get STD handle to AllocConsole
我一直在尝试获取控制台的输出句柄,但它似乎不起作用。我得到它来设置我的文本的颜色,但它没有改变。
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut, 0x0A)
我试过调试它,但我认为我的句柄不对。有没有其他方法可以做到这一点,它不起作用是否正常?有任何修复吗?
谢谢!
编辑: 让我澄清一下,我尝试获取的句柄无效。我不知道如何解决它。我想我会开始寻找替代品;也许我的代码有问题。
由于您指定 hOut
为 INVALID_HANDLE_VALUE
(或可能 NULL
),请尝试调用 GetLastError
找出原因。您可能没有建立控制台会话。
这是 win32 控制台应用程序还是 Windows 子系统应用程序(它有 WinMain
吗?)
您可以在 GetStdHandle
之前尝试 AttachConsole(ATTACH_PARENT_PROCESS)
而不是 AllocConsole
。
在任何一种情况下,AllocConsole
和 AttachConsole
return 一个 BOOL
如果 FALSE
,则表明您可以调用 GetLastError
来找出原因。
确保您没有在上面列出的行之前调用 hOut = GetStdHandle(STD_OUTPUT_HANDLE)
,然后调用 CloseHandle(hOut)
。与 AllocConsole
和 FreeConsole
不同,关闭 std 句柄不是一个好主意。
最后,试试:
#define _WIN32_WINNT 0x0501
在 #include <windows.h>
之前
标准处理程序在进程创建期间初始化,如果您调用 AllocConsole
新控制台会在很晚的时候创建。 AllocConsole
可以 更改标准句柄,但对于启动代码(例如 C 运行时库初始化)使用它们已经太晚了。
在这种情况下最好的做法是 CreateFileW(L"CONOUT$", ...)
,无论您是否附加到 parent 进程的控制台,它都会获得一个控制台句柄,OS 为您创建了一个因为你的 PE header 是 /SUBSYSTEM:CONSOLE
,或者你调用了 AllocConsole
。即使标准句柄被重定向,它也会获得控制台句柄。
如果您认为可以调用 FreeConsole
,您应该确保首先关闭 CreateFile
返回的任何句柄。在控制台保持活动状态直到进程退出的一般情况下,您可以让 OS 在进程清理期间为您关闭句柄。
好的,所以我找到了答案。似乎一个简单的编辑就可以解决它
#define setcsattr(clr) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), clr)
这么小的事情有这么多戏剧性......顺便说一下,@Ben 的回答是正确的答案实际上是正确的。
对于您的问题,只需这样做:
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
这将允许您获得您拥有的任何控制台的句柄。确保将它放在 AllocConsole() 之后;
喜欢吗?!
我一直在尝试获取控制台的输出句柄,但它似乎不起作用。我得到它来设置我的文本的颜色,但它没有改变。
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut, 0x0A)
我试过调试它,但我认为我的句柄不对。有没有其他方法可以做到这一点,它不起作用是否正常?有任何修复吗?
谢谢!
编辑: 让我澄清一下,我尝试获取的句柄无效。我不知道如何解决它。我想我会开始寻找替代品;也许我的代码有问题。
由于您指定 hOut
为 INVALID_HANDLE_VALUE
(或可能 NULL
),请尝试调用 GetLastError
找出原因。您可能没有建立控制台会话。
这是 win32 控制台应用程序还是 Windows 子系统应用程序(它有 WinMain
吗?)
您可以在 GetStdHandle
之前尝试 AttachConsole(ATTACH_PARENT_PROCESS)
而不是 AllocConsole
。
在任何一种情况下,AllocConsole
和 AttachConsole
return 一个 BOOL
如果 FALSE
,则表明您可以调用 GetLastError
来找出原因。
确保您没有在上面列出的行之前调用 hOut = GetStdHandle(STD_OUTPUT_HANDLE)
,然后调用 CloseHandle(hOut)
。与 AllocConsole
和 FreeConsole
不同,关闭 std 句柄不是一个好主意。
最后,试试:
#define _WIN32_WINNT 0x0501
在 #include <windows.h>
标准处理程序在进程创建期间初始化,如果您调用 AllocConsole
新控制台会在很晚的时候创建。 AllocConsole
可以 更改标准句柄,但对于启动代码(例如 C 运行时库初始化)使用它们已经太晚了。
在这种情况下最好的做法是 CreateFileW(L"CONOUT$", ...)
,无论您是否附加到 parent 进程的控制台,它都会获得一个控制台句柄,OS 为您创建了一个因为你的 PE header 是 /SUBSYSTEM:CONSOLE
,或者你调用了 AllocConsole
。即使标准句柄被重定向,它也会获得控制台句柄。
如果您认为可以调用 FreeConsole
,您应该确保首先关闭 CreateFile
返回的任何句柄。在控制台保持活动状态直到进程退出的一般情况下,您可以让 OS 在进程清理期间为您关闭句柄。
好的,所以我找到了答案。似乎一个简单的编辑就可以解决它
#define setcsattr(clr) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), clr)
这么小的事情有这么多戏剧性......顺便说一下,@Ben 的回答是正确的答案实际上是正确的。
对于您的问题,只需这样做:
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
这将允许您获得您拥有的任何控制台的句柄。确保将它放在 AllocConsole() 之后;
喜欢吗?!