最近运行一个MFC对话框窗体程序,编译环境是VS2010,由于需要长时间测试,想像Tomcat那样打开一个控制台输出日志。查看相关资料后,发现其实也不难的,现把调用步骤总结一下。
- 打开控制台输出
在程序的InitInstance()函数中添加如下代码:
#ifdef _DEBUG
AllocConsole();
#endif
因为是调试时需要,所以这里加上_DEBUG宏,有初始化就得有关闭,善始善终嘛。在ExitInstance()函数中添加:
#ifdef _DEBUG
FreeConsole();
#endif
...
return CWinApp::ExitInstance();
这样运行程序,打开对话框同时也打开了控制台终端:
那么如何向终端输出内容呢,需要调用WriteConsole函数:
HANDLE g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
char out[20] = "测试打印内容\n";
WriteConsole(g_hOutput, out, strlen(out), NULL, NULL);
CloseHandle(g_hOutput);
我这里要打印16进制的密钥,需要把字符串转16进制输出:
char buff[17];
char out[50] = "16进制:";
int len = 8;
HANDLE g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
DES((unsigned char*)key, source, (unsigned char*)buff);
for (int i=0; i<len; i++) {
sprintf(out,"%s%02x", out, (unsigned char)buff[i]);
}
WriteConsole(g_hOutput, out, strlen(out), NULL, NULL);
CloseHandle(g_hOutput);
显示结果如下:
这里要注意下CloseHandle函数要在最后调用,如果打印“测试打印内容”后调用,那后面的16进制内容就输出不了了。
- 使用printf函数输出
使用C的程序员都习惯用printf函数,而且格式化输出很方便,这里要想使用printf函数输出,在初始化的时候就麻烦一些了,要进行输出重定向,InitInstance()函数中修改一下:
#ifdef _DEBUG
//AllocConsole();
InitConsoleWindow();
#endif
InitConsoleWindow内容如下:
static int fHandle = -1;
void CDES加密测试App::InitConsoleWindow()
{
FILE *fp;
AllocConsole();
fHandle = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
if (fHandle > 0)
{
fp = _fdopen(fHandle, "w");
*stdout = *fp;
setvbuf(stdout, NULL, _IONBF, 0);
}
}
ExitInstance()函数也修改下:
#ifdef _DEBUG
if (fHandle > 0)
_close(fHandle);
FreeConsole();
#endif
...
return CWinApp::ExitInstance();
还要添加上头文件:
#include <io.h>
#include <fcntl.h>
接下来就可以测试使用printf函数了,在使用的地方别忘添加上头文件:
#include <stdio.h>
...
char buff[17];
char out[50] = "16进制:";
int len = 8;
//HANDLE g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
DES((unsigned char*)key, source, (unsigned char*)buff);
for (int i=0; i<len; i++) {
sprintf(out,"%s%02x", out, (unsigned char)buff[i]);
}
//WriteConsole(g_hOutput, out, strlen(out), NULL, NULL);
//CloseHandle(g_hOutput);
printf("%s\n", out);
运行结果跟使用WriteConsole输出是一样的,这下好用多了。
- 关闭问题解决
无意间先关闭了控制台终端,程序就发生异常了:
看来得监听控制台的事件信息,在对话框的WriteConsole函数中添加事件回调函数:
if (::SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler, TRUE) == FALSE)
{
return FALSE;
}
ConsoleHandler用来处理事件内容,代码如下:
BOOL WINAPI ConsoleHandler(DWORD CEvent)
{
// 处理对应的CTRL_事件
switch (CEvent)
{
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
break;
default:
return FALSE;
}
return TRUE;
}
该函数返回TRUE时程序退出,这里只是简单测试,如果有需要在关闭前处理的内容请编写相应代码。这次再关闭控制台窗口时,程序就不报异常了。