Windows进程内标准输出重定向

上传人:206****923 文档编号:41714115 上传时间:2018-05-30 格式:DOC 页数:3 大小:32.50KB
返回 下载 相关 举报
Windows进程内标准输出重定向_第1页
第1页 / 共3页
Windows进程内标准输出重定向_第2页
第2页 / 共3页
Windows进程内标准输出重定向_第3页
第3页 / 共3页
亲,该文档总共3页,全部预览完了,如果喜欢就下载吧!
资源描述

《Windows进程内标准输出重定向》由会员分享,可在线阅读,更多相关《Windows进程内标准输出重定向(3页珍藏版)》请在金锄头文库上搜索。

1、Windows 进程内标准输出重定向及其在程序调试上的应用一、如何实现 打印调试信息的方法有很多,最常用的是使用标准输出设备(如 printf、cout 等) ,也可以 用 OutPutDebugString 输出、用 DebugView 工具查看,还可以写入日志文件。如果程序运行 需要记录日志(log) ,往往需要打开个文件,或许是写入系统事件、用系统的事件查看器 查看。应用程序打印调试信息、日志的方法往往是确定的,但如果是要编写一个模块或者说组件, 那样的输出信息应该写入哪里呢?或者说程序本身对此也没有明确需求的话,那该怎么办 呢?可喜的是一个进程的标准输出是可以重定向的,所以我建议把调试

2、信息直接打到标准输出 上,这样代码中可以统一使用 cout 或者 printf,然后根据需要将标准输出重定向。Linux 中重定向标准输出就容易了,因为有强大的 dup2 函数。而对于 Windows 的重定向, 貌似往往是用于子进程的,在用 CreateProcess 创建子进程时设置子进程的标准输出句柄。 而我们想要的是重定向自己这个进程的标准输出,那个用不上。我在 MSDN 中也没找到类 似 dup2 的 Win32 API 函数,只有一个 DuplicateHandle 函数,这相当于 linux 中的 dup,也 用不上。这里顺便提下,SetStdHandle 是不能实现重定向的。这

3、个函数的功能是将某句柄指向标准 设备,并不能将标准设备句柄重定向到另外的句柄。于是我就想到,Windows 不是支持一部分 POSIX 标准的吗。于是我找到了一个 CRT 的函数, 叫_dup2,看起来是不是特眼熟,对了,这就是 Windows 中 dup2 的兼容版本。值得注意的是,_dup2 以及与此相关的一系列 CRT 中的 IO 函数(如_read,_write)均以下划 线开头,其余与 linux 大致相同,其参数中所谓的文件描述符与 Win32 中的句柄不一样, 文件描述符实际上是句柄数组的索引,也就是说文件描述符不能与句柄混用。比如 0,1,2 分 别是标准输入、标准输出、标准错

4、误的文件描述符,但句柄值不是这样确定的。文件描述 符不是 Win32 的概念,是 POSIX 中的概念。_dup2 用法与 dup2 大致相同,不多解释,不了解的可以查阅 dup2 相关资料。下面讲点应 用。二、如何应用于调试 写一个模块时,我们可以直接用 cout/printf 来作调试。但是如果这个模块用于图形界面或 许是系统服务呢?这时标准输出看不到了,我们可以用 OutPutDebugString 函数和 DebugView 这样的调试工具。这样就带来一种选择,而选择往往是增加软件复杂度的因素。 所以我的想法是代码中只用 cout/printf,如果需要将其重定向到调试工具中去。如何实

5、现呢,用匿名管道和线程。用一个 pipe,标准输出重定向到其 write 端,然后创建一个线程,线程要做的就是从 pipe 的 read 端读出数据后用 OutPutDebugString 输出。下面是实现代码。头文件是这样子的,构造时重定向,析构时解除:namespace common / 将标准输出重定向到DebugView,保持对象存在即有效class StdoutToDebugString public:StdoutToDebugString();StdoutToDebugString();private:int fds_2;int orign_stdout_;uintptr_t th

6、read_handle_;实现文件:#include #include #include #include #include #include “StdoutRedirect.h“using namespace common;const int kBufferSize = 4096;unsigned _stdcall RedirectThreadProc(void* param) int pipe_read = (int)param;char bufkBufferSize;int bytes_read;do bytes_read = :_read(pipe_read, buf, kBuffer

7、Size);bufbytes_read = 0;:OutputDebugString(buf); while (bytes_read);return 0;StdoutToDebugString:StdoutToDebugString() :_pipe(fds_, kBufferSize, _O_TEXT);orign_stdout_ = _dup(_fileno(stdout);:_dup2(fds_1, _fileno(stdout);thread_handle_ = :_beginthreadex(NULL, 0, RedirectThreadProc, (void*)fds_0, 0,

8、NULL);:CloseHandle(HANDLE)thread_handle_);StdoutToDebugString:StdoutToDebugString() :_dup2(orign_stdout_, _fileno(stdout);测试代码:#include #include #include “./Common/StdoutRedirect.h“using namespace std;using namespace common;void main() StdoutToDebugString redirect;cout “hello“ endl;:system(“pause“);运行时可以看到控制台上并没有打印出 hello,而在 DebugView 中可以看到。三、未解决的问题?因为_read 是阻塞的,我没有办法能安全地结束掉那个线程,所以我无法在析构时等待线程结束。这样如果对象已经析构而线程依然在跑,_read 会引发 assert 导致崩溃。不过在一般情况下,在 main 的开始构造这样一个对象来实现重定向,一直维持到 main 结束,是没有问题的。对于此问题,还望牛人指点。

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号