将Debug调试信息输出到控制台或文件
时常会碰到这种情况,策划们跑过来说程序出错了,然后呱呱啦啦的描述了一大堆也没把问题说清楚。若是能将程序的运行信息自动的记录起来,找bug就方便多了,也就是log功能。
另外为调试程序,时常需要在程序里打入一些调试信息,这样可以更方便的发现BUG。这些调试信息只能在编辑器的调试模式下才能看到,或者借助第三方软件比如debugview等,但是会受到编译环境的限制,又不可能每次都带着debugview运行程序。。。若能将调试信息自动记录到log文件就方便多了。
在调试模式下,调试器之所以能够得到信息,是因为捕捉了程序中的 OutputDebugString() 输出的信息。所以如果我们能够自己写程序捕捉OutputDebugString()函数输出的信息,就能解决上述的需求了。有关OutputDebugString()函数的原理请看这里:http://www.unixwiz.net/techtips/outputdebugstring.html,也可在本blog查看翻译版本。
原理看明白后,实现起来就很容易了。下面给出具体代码:
1const MAX_DebugBuffer = 4096; // 应用程序和调试器之间传递数据是通过一个 4KB 大小的共享内存块完成的
2
3typedef struct dbwin_buffer {
4 DWORD dwProcessId;
5 char data[4096-sizeof(DWORD)];
6}DEBUGBUFFER,*PDEBUGBUFFER;
7
8// 线程函数
9void WINAPI DebugTrackProc(PVOID pvParam)
10{
11 HANDLE hMapping = NULL;
12 HANDLE hAckEvent = NULL;
13 HANDLE hReadyEvent = NULL;
14 PDEBUGBUFFER pdbBuffer = NULL;
15 TCHAR tzBuffer[MAX_DebugBuffer];
16
17 // 打开事件句柄
18 hAckEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("DBWIN_BUFFER_READY"));
19 if(hAckEvent == NULL)
20 {
21 CloseHandle(hAckEvent);
22 return;
23 }
24
25 hReadyEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("DBWIN_DATA_READY"));
26 if(hReadyEvent == NULL)
27 {
28 CloseHandle(hReadyEvent);
29 return;
30 }
31
32 // 创建文件映射
33 hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAX_DebugBuffer, TEXT("DBWIN_BUFFER"));
34 if(hMapping == NULL)
35 {
36 CloseHandle(hMapping);
37 return;
38 }
39
40 // 映射调试缓冲区
41 pdbBuffer = (PDEBUGBUFFER) MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
42
43 // 循环
44 while( true )
45 {
46 // 激活事件
47 SetEvent(hAckEvent);
48 // 等待缓冲区数据
49 if ( WaitForSingleObject(m_hReadyEvent, INFINITE) == WAIT_OBJECT_0 )
50 {
51 // 保存信息,这就是我们想要的,有了这个信息,想打log或是输出到控制台就都可以啦
52 tzBuffer = pdbBuffer->szString;
53 }
54 }
55
56 // 释放
57 if (pdbBuffer)
58 {
59 UnmapViewOfFile(pdbBuffer);
60 }
61 CloseHandle(hMapping);
62 CloseHandle(hReadyEvent);
63 CloseHandle(hAckEvent);
64}
2
3typedef struct dbwin_buffer {
4 DWORD dwProcessId;
5 char data[4096-sizeof(DWORD)];
6}DEBUGBUFFER,*PDEBUGBUFFER;
7
8// 线程函数
9void WINAPI DebugTrackProc(PVOID pvParam)
10{
11 HANDLE hMapping = NULL;
12 HANDLE hAckEvent = NULL;
13 HANDLE hReadyEvent = NULL;
14 PDEBUGBUFFER pdbBuffer = NULL;
15 TCHAR tzBuffer[MAX_DebugBuffer];
16
17 // 打开事件句柄
18 hAckEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("DBWIN_BUFFER_READY"));
19 if(hAckEvent == NULL)
20 {
21 CloseHandle(hAckEvent);
22 return;
23 }
24
25 hReadyEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("DBWIN_DATA_READY"));
26 if(hReadyEvent == NULL)
27 {
28 CloseHandle(hReadyEvent);
29 return;
30 }
31
32 // 创建文件映射
33 hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAX_DebugBuffer, TEXT("DBWIN_BUFFER"));
34 if(hMapping == NULL)
35 {
36 CloseHandle(hMapping);
37 return;
38 }
39
40 // 映射调试缓冲区
41 pdbBuffer = (PDEBUGBUFFER) MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
42
43 // 循环
44 while( true )
45 {
46 // 激活事件
47 SetEvent(hAckEvent);
48 // 等待缓冲区数据
49 if ( WaitForSingleObject(m_hReadyEvent, INFINITE) == WAIT_OBJECT_0 )
50 {
51 // 保存信息,这就是我们想要的,有了这个信息,想打log或是输出到控制台就都可以啦
52 tzBuffer = pdbBuffer->szString;
53 }
54 }
55
56 // 释放
57 if (pdbBuffer)
58 {
59 UnmapViewOfFile(pdbBuffer);
60 }
61 CloseHandle(hMapping);
62 CloseHandle(hReadyEvent);
63 CloseHandle(hAckEvent);
64}
版权声明:本篇为原创文章,允许转载,但转载时请务必以超链接形式标明文章的原始出处和作者信息。请尊重本人的劳动成果,谢谢!
小祥的BLOG http://xfxsworld.cnblogs.com