zhenlongyang
驱动小牛
驱动小牛
  • 注册日期2004-10-28
  • 最后登录2010-07-26
  • 粉丝1
  • 关注0
  • 积分729分
  • 威望100点
  • 贡献值0点
  • 好评度66点
  • 原创分0分
  • 专家分0分
阅读:3534回复:15

如何用API实现将输出到控制台屏幕的内容改输出到一个文件中?

楼主#
更多 发布于:2007-01-18 21:44
基本目标就是:在基于控制台的程序中,调用某个或几个API函数后,此后的所有向屏幕输出的函数,如printf()等,其输出内容就会输出到一个磁盘文件中,也就是输出重定向,但是我想知道在API级别上是如何实现的而不是调用运行时库函数来实现。
我曾经试过如下方法:
hFile = CreateFile(...);
SetStdHandle(STD_OUTPUT_HANDLE, hFile);
可是,尽管上述函数调用都成功了,但是其后的printf()函数的输出还是输出到屏幕上,而不是到文件中,文件中什么都没写入,请高手们给详细解答一下,谢谢!
newyear
驱动小牛
驱动小牛
  • 注册日期2007-01-11
  • 最后登录2008-09-10
  • 粉丝0
  • 关注0
  • 积分1001分
  • 威望122点
  • 贡献值0点
  • 好评度120点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2007-01-18 22:42
用管道...
缘起缘灭-----相识就是有缘-----
zhenlongyang
驱动小牛
驱动小牛
  • 注册日期2004-10-28
  • 最后登录2010-07-26
  • 粉丝1
  • 关注0
  • 积分729分
  • 威望100点
  • 贡献值0点
  • 好评度66点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2007-01-19 19:05
用了,还是白费力!
wht0395
驱动小牛
驱动小牛
  • 注册日期2006-07-06
  • 最后登录2009-06-10
  • 粉丝0
  • 关注0
  • 积分583分
  • 威望135点
  • 贡献值0点
  • 好评度122点
  • 原创分0分
  • 专家分0分
地板#
发布于:2007-01-19 20:51
printf()函数在程序初始化时被绑定到标准输出上

你看CRT代码
什么不懂的学生
zhenlongyang
驱动小牛
驱动小牛
  • 注册日期2004-10-28
  • 最后登录2010-07-26
  • 粉丝1
  • 关注0
  • 积分729分
  • 威望100点
  • 贡献值0点
  • 好评度66点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2007-01-20 17:52
既然能控制子进程的输出,那么为什么就不能控制本进程的输出呢?若是SetStdHandle()函数对本进程毫无效用,那么它还有什么用处呢?调用该函数后,对本进程都有什么有意义的影响呢?
wht0395
驱动小牛
驱动小牛
  • 注册日期2006-07-06
  • 最后登录2009-06-10
  • 粉丝0
  • 关注0
  • 积分583分
  • 威望135点
  • 贡献值0点
  • 好评度122点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2007-01-20 21:50
SetStdHandle 仅仅是对 Peb->ProcessParameters里的 StandardInput 、StandardOutput 、StandardError 3个变量的赋值而已。

printf内部实现类似于
    sprintf(buf,format,arglist)
     fwrite(stdout,buf);

其中stdout为CRT内部变量,在初始化时已经被设置为 stdout=GetStdHandle(STD_OUTPUT_HANDLE);
(具体看CRT代码,ioinit()),所以,即使你在程序里改变了Peb->ProcessParameters里的 StandardOutput ,stdout没有变化

想重定向PRINTF之类标准库函数,想办法改变stdout吧
什么不懂的学生
zhenlongyang
驱动小牛
驱动小牛
  • 注册日期2004-10-28
  • 最后登录2010-07-26
  • 粉丝1
  • 关注0
  • 积分729分
  • 威望100点
  • 贡献值0点
  • 好评度66点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2007-01-23 18:04
一定可以实现,但问题是有人知道该如何实现么?
wht0395
驱动小牛
驱动小牛
  • 注册日期2006-07-06
  • 最后登录2009-06-10
  • 粉丝0
  • 关注0
  • 积分583分
  • 威望135点
  • 贡献值0点
  • 好评度122点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2007-01-23 20:44
晕死!当然可以实现!
什么不懂的学生
zhenlongyang
驱动小牛
驱动小牛
  • 注册日期2004-10-28
  • 最后登录2010-07-26
  • 粉丝1
  • 关注0
  • 积分729分
  • 威望100点
  • 贡献值0点
  • 好评度66点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2007-01-24 20:21
你所说的就是调用freopen()函数来改,但我想调用API函数来改,能该么?
wht0395
驱动小牛
驱动小牛
  • 注册日期2006-07-06
  • 最后登录2009-06-10
  • 粉丝0
  • 关注0
  • 积分583分
  • 威望135点
  • 贡献值0点
  • 好评度122点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2007-01-25 00:21
“你所说的就是调用freopen()函数来改”,我什么都没说。
什么不懂的学生
zhenlongyang
驱动小牛
驱动小牛
  • 注册日期2004-10-28
  • 最后登录2010-07-26
  • 粉丝1
  • 关注0
  • 积分729分
  • 威望100点
  • 贡献值0点
  • 好评度66点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2007-01-30 22:41
如果要直接修改运行时库函数的内部变量的话,这不是我想要的方法,我只想通过调用API函数来实现,即把RTL"蒙在鼓里"的方法,给个实现代码来看看?
还有,有人能让cprintf()函数的输出不输出到屏幕上么?
zhenlongyang
驱动小牛
驱动小牛
  • 注册日期2004-10-28
  • 最后登录2010-07-26
  • 粉丝1
  • 关注0
  • 积分729分
  • 威望100点
  • 贡献值0点
  • 好评度66点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2007-02-11 19:50
就没有高手指点一下么?
geland
驱动牛犊
驱动牛犊
  • 注册日期2003-12-28
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分25分
  • 威望251点
  • 贡献值0点
  • 好评度54点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2007-02-12 10:37
bool redirect_convert_io(const char* command,HANDLE* ph)
{

    Assert(command);
    Assert(ph);

   SECURITY_ATTRIBUTES saAttr;
   BOOL fSuccess;
 
   // Set the bInheritHandle flag so pipe handles are inherited.
 
   saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
   saAttr.bInheritHandle = TRUE;
   saAttr.lpSecurityDescriptor = NULL;
 
    // Save the handle to the current STDIN.
 
   hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
 
    // Create a pipe for the child process's STDIN.
 
   if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
      return false;
 
    // Set a read handle to the pipe to be STDIN.
 
   if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd))
      return false;
 
    // Duplicate the write handle to the pipe so it is not inherited.
 
   fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
      GetCurrentProcess(), &hChildStdinWrDup, 0,
      FALSE,                  // not inherited
      DUPLICATE_SAME_ACCESS);
   if (! fSuccess)
      return false;
 
   CloseHandle(hChildStdinWr);
 
    // Now create the child process.
  
   fSuccess = CreateChildProcess(command,ph);
   if (! fSuccess)
      return false;
 
    // After process creation, restore the saved STDIN and STDOUT.
 
   if (! SetStdHandle(STD_INPUT_HANDLE, hSaveStdin))
      return false;
 
   return true;
}
wht0395
驱动小牛
驱动小牛
  • 注册日期2006-07-06
  • 最后登录2009-06-10
  • 粉丝0
  • 关注0
  • 积分583分
  • 威望135点
  • 贡献值0点
  • 好评度122点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2007-02-12 11:48
搞不懂你要干嘛.对付已经运行的程序??

实在没办法,懒方法还有个HOOK.
分析下RTL代码,看下最终调用的是哪个WriteXYZ,HOOK 掉.
根据WRITE的HANDLE是不是STDOUT来决定是否重定向.
什么不懂的学生
zhenlongyang
驱动小牛
驱动小牛
  • 注册日期2004-10-28
  • 最后登录2010-07-26
  • 粉丝1
  • 关注0
  • 积分729分
  • 威望100点
  • 贡献值0点
  • 好评度66点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2007-02-13 20:54
看来是我没说清楚,再说明一下:
比如,有这样一个源程序:
void fun(void)
{
    printf("You are welcome!\n");
}

void main(void)
{
    fun();
}

现在,我在main函数中加一条代码,即:
void main(void)
{
    Redirect();
    fun();
}

然后重新编译程序,运行,这时fun()的所有输出就都输出到一个文件中去了。那么,这个Redirect()函数要如何编写呢?(只允许在Redirect()中调用Windows API,不能调用RTL函数)
zhenlongyang
驱动小牛
驱动小牛
  • 注册日期2004-10-28
  • 最后登录2010-07-26
  • 粉丝1
  • 关注0
  • 积分729分
  • 威望100点
  • 贡献值0点
  • 好评度66点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2007-11-29 22:39
老声长谈,我还是没有解决这个问题。
游客

返回顶部