• 捕获控制台输出信息


    启动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启动一个控制台程序,把输入和输出用管道重定向,

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

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

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

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

    具体的实现如下:

    代码
    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, 0then
      
    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

  • 相关阅读:
    冲销收货
    收货MIGO
    删除PO
    创建po
    File的功能--> 获取功能-->所有的根目录 | 创建文件功能,但是如果文件已经存在-->不再创建(新手)
    在d盘创建文件夹,里面有aaa.txt/bbb.txt/ccc.txt,然后遍历出aaa文件夹下的文件(新手)
    创建一个唱歌类集合,创建一个电影类集合,让其归类打印(新手)
    抛出异常(新手)
    Map-->HashMap练习(新手)
    JAVA-迭代器增强型for循环。(新手)
  • 原文地址:https://www.cnblogs.com/iihe602/p/1652307.html
Copyright © 2020-2023  润新知