捕获控制台输出信息

启动DOS或者控制台程序,如何捕获运行时的输出信息?

比如,在dos窗口下,输入dir捕获文件夹列表信息?

有两篇文章已经说明了这个问题:

http://www.delphi3000.com/articles/article_2112.asp
http:
//www.delphi3000.com/articles/article_2298.asp
但是,他们都是在进程结束之后才获取输出信息

这样会有一些问题:

1)createPipe必须制定足够的size,否则,程序会死掉

2)如果程序createProcess成功,但是内部命令出错,会导致readfile时死掉

 

Microsoft Knowledge Base Article - Q190351
HOWTO: Spawn Console Processes 
with Redirected Standard Handles
http:
//support.microsoft.com/default.aspx?scid=kb;en-us;Q190351

Microsoft Knowledge Base Article 
- Q150956
INFO: Redirection Issues on Windows 
95 MS-DOS Applications
http:
//support.microsoft.com/default.aspx?scid=KB;EN-US;Q150956

 

基本的思想是用CreateProcess启动一个控制台程序,把输入和输出用管道重定向,

允许调用进程访问控制台程序的输出信息

 

在进程依然运行中捕获输出时非常重要的,如果输出管道发生溢出,就会被阻止,

控制台程序就不能够将新的信息就覆盖到输出管道,并且导致程序停止,这种情况下

会锁死的:父进程等待子进程结束,而子进程等待父进程清空缓冲区

 

具体的实现如下:

ExpandedBlockStart.gif 代码
procedure  CaptureConsoleOutput(DosApp :  string ;AMemo : TMemo);
const
  ReadBuffer  =   1048576 ;   //   1  MB Buffer
var
  Security            : TSecurityAttributes;
  ReadPipe,WritePipe  : THandle;
  start               : TStartUpInfo;
  ProcessInfo         : TProcessInformation;
  Buffer              : Pchar;
  TotalBytesRead,
  BytesRead           : DWORD;
  Apprunning,n,
  BytesLeftThisMessage,
  TotalBytesAvail : integer;
begin
  
with  Security  do
  
begin
    nlength              : =  SizeOf(TSecurityAttributes);
    binherithandle       : =  true;
    lpsecuritydescriptor : =   nil ;
  
end ;

  
if  CreatePipe (ReadPipe, WritePipe, @Security,  0 then
  
begin
    
//  Redirect In -   and  Output through STARTUPINFO structure

    Buffer  : =  AllocMem(ReadBuffer  +   1 );
    FillChar(Start,Sizeof(Start),# 0 );
    start.cb          : =  SizeOf(start);
    start.hStdOutput  : =  WritePipe;
    start.hStdInput   : =  ReadPipe;
    
start.hStdError   : = WritePipe; // 控制台错误信息也输出
    start.dwFlags     :
=  STARTF_USESTDHANDLES  +  STARTF_USESHOWWINDOW;
    start.wShowWindow : =  SW_HIDE;

    
//  Create a Console Child Process  with  redirected input  and  output

    
if  CreateProcess( nil       ,PChar(DosApp),
                     @Security,@Security,
                     true     ,CREATE_NO_WINDOW  or  NORMAL_PRIORITY_CLASS,
                     
nil       , nil ,
                     start    ,ProcessInfo)  then
    
begin
      n: = 0 ;
      TotalBytesRead: = 0 ;
      
repeat
        
//  Increase counter  to  prevent an endless loop  if  the process  is  dead
        Inc(n, 1 );
        
        
//  wait  for   end   of  child process
        Apprunning : =  WaitForSingleObject(ProcessInfo.hProcess, 100 );
        Application.ProcessMessages;

        
//  it  is  important  to   read  from time  to  time the output information
        
//  so that the pipe  is   not  blocked by an overflow. New information
        
//  can be written from the console app  to  the pipe only  if  there  is
        
//  enough buffer space.

        
if   not  PeekNamedPipe(ReadPipe        ,@Buffer[TotalBytesRead],
                             ReadBuffer      ,@BytesRead,
                             @TotalBytesAvail,@BytesLeftThisMessage)  then   break
        
else   if  BytesRead  >   0   then
          ReadFile(ReadPipe,Buffer[TotalBytesRead],BytesRead,BytesRead, nil );
        TotalBytesRead: = TotalBytesRead + BytesRead;
      
until  (Apprunning  <>  WAIT_TIMEOUT)  or  (n  >   150 );

      Buffer[TotalBytesRead]: =  # 0 ;
      OemToChar(Buffer,Buffer);
      AMemo.Text : =  AMemo.text  +  StrPas(Buffer);
    
end ;
    FreeMem(Buffer);
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(ReadPipe);
    CloseHandle(WritePipe);
  
end ;
end


摘自http://www.delphi3000.com/articles/article_3361.asp

转载于:https://www.cnblogs.com/iihe602/archive/2010/01/20/1652307.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值