无法写入 AllocConsole()
Unable to write to AllocConsole()
我有一个 cpp dll,我想在注入后将文本打印到控制台。我使用 AllocConsole() 创建控制台,因为它是最简单的方法,但我无法在控制台中编写。
当我尝试 printf() 时,没有任何反应。我也试过 std::cout<<"";但也没有结果。
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
AllocConsole();
printf("Injected");
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)main, NULL, NULL, NULL);
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
通过AllocConsole()
分配新控制台后,您需要重新打开标准流(stdout
、stderr
、stdin
)才能使用它们.
您可以使用 freopen
来实现(在较新版本的 Visual Studio 中您需要使用 freopen_s
)
示例:
FILE *fDummy;
freopen_s(&fDummy, "CONIN$", "r", stdin);
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONOUT$", "w", stdout);
如果您想使用已弃用的 freopen
,您可以 disable the warning 通过 #define
ing _CRT_SECURE_NO_WARNINGS
。
如果您还想使用宽字符流(std::wcout
、std::wcerr
等...),您需要使用 CONOUT$
调用 SetStdHandle()
to set a new output handle for your process. You can get the required file handle for this by calling CreateFile()
/ CONIN$
作为文件名:
HANDLE hConOut = CreateFile(_T("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
此外,如果您在重新打开之前尝试使用其中一个流,它们将具有 std::ios_base::badbit
and std::ios_base::failbit
在他们的 iostate
中设置,因此后续的写入/读取将被忽略。
您可以使用 .clear()
重置流状态,之后您可以再次 read/write from/to 流:
std::cout.clear();
std::cin.clear();
这是在 AllocConsole()
之后重新打开所有流的完整示例:
void CreateConsole()
{
if (!AllocConsole()) {
// Add some error handling here.
// You can call GetLastError() to get more info about the error.
return;
}
// std::cout, std::clog, std::cerr, std::cin
FILE* fDummy;
freopen_s(&fDummy, "CONOUT$", "w", stdout);
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONIN$", "r", stdin);
std::cout.clear();
std::clog.clear();
std::cerr.clear();
std::cin.clear();
// std::wcout, std::wclog, std::wcerr, std::wcin
HANDLE hConOut = CreateFile(_T("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE hConIn = CreateFile(_T("CONIN$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
SetStdHandle(STD_ERROR_HANDLE, hConOut);
SetStdHandle(STD_INPUT_HANDLE, hConIn);
std::wcout.clear();
std::wclog.clear();
std::wcerr.clear();
std::wcin.clear();
}
我有一个 cpp dll,我想在注入后将文本打印到控制台。我使用 AllocConsole() 创建控制台,因为它是最简单的方法,但我无法在控制台中编写。
当我尝试 printf() 时,没有任何反应。我也试过 std::cout<<"";但也没有结果。
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
AllocConsole();
printf("Injected");
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)main, NULL, NULL, NULL);
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
通过AllocConsole()
分配新控制台后,您需要重新打开标准流(stdout
、stderr
、stdin
)才能使用它们.
您可以使用 freopen
来实现(在较新版本的 Visual Studio 中您需要使用 freopen_s
)
示例:
FILE *fDummy;
freopen_s(&fDummy, "CONIN$", "r", stdin);
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONOUT$", "w", stdout);
如果您想使用已弃用的 freopen
,您可以 disable the warning 通过 #define
ing _CRT_SECURE_NO_WARNINGS
。
如果您还想使用宽字符流(std::wcout
、std::wcerr
等...),您需要使用 CONOUT$
调用 SetStdHandle()
to set a new output handle for your process. You can get the required file handle for this by calling CreateFile()
/ CONIN$
作为文件名:
HANDLE hConOut = CreateFile(_T("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
此外,如果您在重新打开之前尝试使用其中一个流,它们将具有 std::ios_base::badbit
and std::ios_base::failbit
在他们的 iostate
中设置,因此后续的写入/读取将被忽略。
您可以使用 .clear()
重置流状态,之后您可以再次 read/write from/to 流:
std::cout.clear();
std::cin.clear();
这是在 AllocConsole()
之后重新打开所有流的完整示例:
void CreateConsole()
{
if (!AllocConsole()) {
// Add some error handling here.
// You can call GetLastError() to get more info about the error.
return;
}
// std::cout, std::clog, std::cerr, std::cin
FILE* fDummy;
freopen_s(&fDummy, "CONOUT$", "w", stdout);
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONIN$", "r", stdin);
std::cout.clear();
std::clog.clear();
std::cerr.clear();
std::cin.clear();
// std::wcout, std::wclog, std::wcerr, std::wcin
HANDLE hConOut = CreateFile(_T("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE hConIn = CreateFile(_T("CONIN$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
SetStdHandle(STD_ERROR_HANDLE, hConOut);
SetStdHandle(STD_INPUT_HANDLE, hConIn);
std::wcout.clear();
std::wclog.clear();
std::wcerr.clear();
std::wcin.clear();
}