WinMain中stdout无输出问题排查 - C/VS2017
解决Win32 GUI程序中printf系列函数无法输出到标准输出的问题
嘿,这个问题我之前帮不少人捋清楚过——你用WinMain作为入口的Win32 GUI程序,默认是没有关联控制台窗口的,stdout、stderr这些标准流没有对应的输出目标,所以printf/printf_s/fprintf_s(stdout,...)都看不到输出,而文件写入正常是因为文件是独立的IO对象,不受控制台影响。
结合你已经排查过子系统、预处理器宏的情况,给你几个实用的解决思路:
1. 手动创建控制台并绑定标准流
这是最直接的办法,在WinMain的开头添加代码,手动分配一个控制台窗口,并把stdout重定向到这个控制台:
#include <winsock2.h> #include <ws2tcpip.h> #include <stdlib.h> #include <stdio.h> #include <math.h> // 别忘了包含这个头文件,AllocConsole需要它 #include <windows.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 分配控制台窗口 AllocConsole(); // 重定向stdout到控制台 FILE* consoleOut; freopen_s(&consoleOut, "CONOUT$", "w", stdout); FILE * pFile = fopen("outputTest.txt", "w"); fprintf(pFile, "At top of main1.\n"); //works printf("At top of main2.\n"); //现在能输出到控制台了 printf_s("At top of main3.\n"); //同样生效 fprintf_s(stdout, "At top of main4.\n"); //正常输出 fflush(stdout); fclose(pFile); // 程序结束前可以关闭控制台,也可以留着让用户看输出 // FreeConsole(); return FALSE; }
这里的CONOUT$是Windows系统定义的控制台输出设备名称,通过freopen_s把stdout绑定到它之后,所有标准输出的内容都会显示在新弹出的控制台窗口里。
2. 切换到控制台子系统(如果不需要GUI界面)
如果你其实不需要GUI窗口,只是误创建了Win32 GUI项目,可以把程序改成控制台子系统:
- 在VS2017中右键项目 -> 属性 -> 链接器 -> 系统 -> 子系统,选择
控制台 (/SUBSYSTEM:CONSOLE) - 把入口函数从
WinMain改成main,这样程序启动时会自动弹出控制台窗口,printf系列函数就能正常输出了。
3. 用调试输出替代标准输出(适合GUI程序调试)
如果不想弹出控制台窗口,只是需要调试时查看输出,可以用Windows的OutputDebugString函数,它会把内容输出到Visual Studio的输出窗口里:
// 输出宽字符串 OutputDebugStringW(L"At top of main.\n"); // 或者输出窄字符串 OutputDebugStringA("At top of main.\n");
然后在VS中打开调试 -> 窗口 -> 输出,就能看到这些调试信息了,这个方法对GUI程序的调试非常友好,不会额外弹出窗口。
另外补充一句:你添加的_CRT_SECURE_NO_DEPRECATE宏其实和这个输出问题无关,它只是用来屏蔽旧版C函数的安全警告,不影响标准流的输出逻辑。
内容的提问来源于stack exchange,提问作者mpchenette
相关产品推荐
相关产品推荐

