Win32程序添加控制台日志输出以及卡死问题的解决

1 篇文章 0 订阅
1 篇文章 0 订阅

在使用c/c++学习Win32编程的过程中,有时候需要对程序运行情况进行观察与调试。使用传统的控制台进行输出日志就是很方便的一种方法。下面给出添加日志控制台的一个函数。
输入参数hWnd为窗口句柄,用来生成消息框,作为消息框的所有者窗口的句柄。

BOOL addConsole(HWND hWnd) {
	HANDLE hStdin;
	DWORD mode;
	
	if (AllocConsole() == 0) {
		MessageBox(hWnd, _T("AllocConsole failed!"), NULL, MB_OK);
		return false;
	}
	hStdin = GetStdHandle(STD_INPUT_HANDLE);
	GetConsoleMode(hStdin, &mode);
	mode &= ~ENABLE_QUICK_EDIT_MODE;
	mode &= ~ENABLE_INSERT_MODE;
	mode &= ~ENABLE_MOUSE_INPUT;
	SetConsoleMode(hStdin, mode);

	if (freopen("conout$", "w", stdout) == NULL) {
		MessageBox(hWnd, _T("freopen stdout failed!"), NULL, MB_OK);
		return false;
	}
	if (freopen("conin$", "r", stdin) == NULL) {
		MessageBox(hWnd, _T("freopen stdin failed!"), NULL, MB_OK);
		return false;
	}
	if (freopen("conerr$", "w", stderr) == NULL) {
		MessageBox(hWnd, _T("freopen stderr failed!"), NULL, MB_OK);
		return false;
	}

	printf("添加控制台成功!\n");
	return true;
}
  • AllocConsole()函数
    为当前线程分配一个控制台窗口,一般来说一个线程只能分配一个控制台窗口,多次分配会失败并返回0。windows系统用特殊的文件名:conout$conin$ 以及conerr$ 来标识控制台输入、输出以及错误输出缓冲区。当使用AllocConsole()分配成功(或线程成功挂载到一个控制台)时,上述三个描述符变得有效,否则使用这些描述符会使程序报错。
  • freopen()函数
    c语言标准库函数,用来重定向输入输出流,包含于stdio.h头文件之中。当我们使用printf()与scanf()函数的时候,会默认调用stdout与stdin的输入输出流。如果我们创建的是控制台项目,那么stdout与stdin会默认使用控制台作为输入输出文件。但是Win32 GUI程序初始不带有控制台窗口,因此在分配了控制台后如果要使用它,还需要将stdin与stdout重定向到指定的控制台窗口。
    第一个参数是重定向到的文件。如果重定向到硬盘内的路径,则会打开(或创建)这个文件,用以输出或输入数据。特殊地,conout$conin$ 以及conerr$ 文件名指示输出输入到控制台中。
  • 控制台卡死
    在使用控制台的时候,如果鼠标选中或尝试输入内容,线程会被堵塞导致程序卡死,只有输入回车将控制台缓冲清空时程序才会恢复正常。这个时候可以右键控制台窗口的标题栏,设置属性,将快速编辑模式和插入模式移除。更方便地,可以使用SetConsoleMode()函数移除这些模式。这个时候,控制台充当了仅可读临时日志的功能,而且不能选中文字内容。

本文参考了@小七爱淘气的文章。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现一个基于TCP协议的网络聊天室,可以分为客户端和服务器端两个部分,下面分别讲述。 客户端: 1. 创建一个Win32控制台应用程序项目。 2. 添加头文件和链接库:`#include <winsock2.h>`和`#pragma comment(lib, "ws2_32.lib")`。 3. 初始化Winsock库:调用`WSAStartup`函数,参数为指定版本号和WSADATA结构体指针。 4. 创建套接字:调用`socket`函数,参数为地址族、套接字类型和协议。创建成功后,返回套接字描述符。 5. 连接服务器:调用`connect`函数,参数为套接字描述符、服务器地址和端口号。 6. 发送和接收数据:调用`send`和`recv`函数,参数为套接字描述符、数据缓冲区和数据长度。 7. 关闭套接字:调用`closesocket`函数,参数为套接字描述符。 8. 释放Winsock库:调用`WSACleanup`函数。 服务器端: 1. 创建一个Win32控制台应用程序项目。 2. 添加头文件和链接库:`#include <winsock2.h>`和`#pragma comment(lib, "ws2_32.lib")`。 3. 初始化Winsock库:调用`WSAStartup`函数,参数为指定版本号和WSADATA结构体指针。 4. 创建套接字:调用`socket`函数,参数为地址族、套接字类型和协议。创建成功后,返回套接字描述符。 5. 绑定套接字:调用`bind`函数,参数为套接字描述符、服务器地址和端口号。 6. 监听套接字:调用`listen`函数,参数为套接字描述符和最大连接数。 7. 接受连接:调用`accept`函数,参数为套接字描述符、客户端地址和端口号。创建成功后,返回新的套接字描述符。 8. 发送和接收数据:调用`send`和`recv`函数,参数为套接字描述符、数据缓冲区和数据长度。 9. 关闭套接字:调用`closesocket`函数,参数为套接字描述符。 10. 释放Winsock库:调用`WSACleanup`函数。 以上是基本的实现流程,具体实现过程中还需要考虑数据的传输格式、多个客户端的连接管理、消息的广播等问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值