我有一个DLL,我使用AllocConsole()和cout来显示数据以进行调试.
它曾经工作正常但是因为我将我的编译器(Visual Studio 2012)更新到最新的dll只显示控制台而不是print/couts.
我不明白为什么会发生这种情况.
有任何想法吗?
我的部分代码
__declspec(dllexport) INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
switch(Reason)
{
case DLL_PROCESS_ATTACH:
AllocConsole();
DisableThreadLibraryCalls(hDLL);
//
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pSend, MySend);
if(DetourTransactionCommit() == NO_ERROR)
cout << "[" << MySend << "] successfully detoured." << endl;
Run Code Online (Sandbox Code Playgroud)
但是什么都没有显示
Vla*_*nko 62
我隐约回想起你可能需要将stdout重定向到控制台.我可能错了(因为你的代码工作得很早):
AllocConsole();
freopen("CONOUT$", "w", stdout);
std::cout << "This works" << std::endl;
Run Code Online (Sandbox Code Playgroud)
Tur*_*ght 18
通过 分配新的控制台后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);
Run Code Online (Sandbox Code Playgroud)
如果要使用已弃用的freopen
,可以通过ing禁用警告。#define
_CRT_SECURE_NO_WARNINGS
如果您还想使用宽字符流(std::wcout
、std::wcerr
等...),则需要调用SetStdHandle()
为您的进程设置新的输出句柄。您可以通过CreateFile()
使用CONOUT$
/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);
Run Code Online (Sandbox Code Playgroud)
此外,如果您在重新打开流之前尝试使用其中一个流,它们的std::ios_base::badbit
和std::ios_base::failbit
将设置在它们的 中iostate
,因此后续的写入/读取将被忽略。
您可以使用 重置流状态.clear()
,之后您可以再次从/向流读取/写入:
std::cout.clear();
std::cin.clear();
Run Code Online (Sandbox Code Playgroud)
下面是在 之后重新打开所有流的完整示例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();
}
Run Code Online (Sandbox Code Playgroud)
小智 8
这可以使用 vs2015 和以下行std::cout.clear()
if (!AllocConsole())
MessageBox(NULL, L"The console window was not created", NULL, MB_ICONEXCLAMATION);
FILE* fp;
freopen_s(&fp, "CONOUT$", "w", stdout);
printf("Hello console on\n");
std::cout.clear();
std::cout << "Cout line one." << std::endl;
cout << "Cout line two." << std::endl;
MessageBox(NULL, (L"Pause to see console output."), (L"Pause Here"), MB_OK | MB_SYSTEMMODAL | MB_ICONEXCLAMATION);
fclose(fp);
if (!FreeConsole())
MessageBox(NULL, L"Failed to free the console!", NULL, MB_ICONEXCLAMATION);
Run Code Online (Sandbox Code Playgroud)