HanDs
管理员

[Delphi文章] 调用DOS程序,并取得该程序的运行结果输出 



如何调用DOS程序,并取得该程序的运行结果输出

Q Allen:
    操作系统: Windows
    编程工具: Delphi7
    问题: 请问如何在程序中调用另一个DOS程序,并取得该程序的运行结果输出。
    我知道可以用WINEXEC(),SHELLEXECUTE等运行一个程序,但如何得到结果,
    例如,运行CMD.EXE /C DIR,如何得到该程序返回的字符?
    水平: 中级

A回答:

    可以使用CreatePipe建立管道,然后把DOS程序的输出转向到你建立的管道,
    这样就可以获得输出结果。下面的例子调用C:\WINDOWS\TRACERT.EXE,
    并将输出保存在c:\trace.txt中。
    unit RoutingThrd;
    
    {Martin Harvey 8/5/98}
    
    interface
    
    uses
     Classes,Windows,SysUtils;
    
    const
     OutputFile='c:\trace.txt';
     ErrorFile='c:\trace.err';
    
    type
     TRoutingThread = class(TThread)
     private
     { Private declarations }
     ToChildReadHandle,ToChildWriteHandle,
     FromChildReadHandle,FromChildWriteHandle:THandle;
     SavedStdIn,SavedStdOut:THandle;
     SecurityAttributes:TSecurityAttributes;
     ApplicationName:PChar;
     CommandLine:PChar;
     StartupInfo:TStartupInfo;
     ProcessInformation:TProcessInformation;
     ReadBuffer:array[0..15] of Byte;
     MonitorChild:boolean;
     ErrorCode:longint;
     ReadOK:boolean;
     PInputHost:Pchar;
     protected
     procedure Execute; override;
     destructor Destroy;override;
     public
     TraceOutput:TMemoryStream;
     InputHost:string;
     constructor Create(CreateSuspended:Boolean);
     end;
    
    implementation
    
    uses MainForm;
    
    destructor TRoutingThread.Destroy;
    begin
    TraceOutput.Free;
    inherited Destroy;
    end;
    
    constructor TRoutingThread.Create(CreateSuspended:boolean);
    begin
    inherited Create(CreateSuspended);
    TraceOutput:=TMemoryStream.Create;
    end;
    
    procedure TRoutingThread.Execute;
    
    var
     BytesRead:integer;
    
    begin
     {We need to:
     1. Set up the security attributes structure
     2. Create both pipes.
     3. Save our standard handles
     4. Redirect our standard read handle to "ToChildReadHandle"
     5. Redirect our standard write handle to "FromChildWriteHandle"
     6. Redirect our standard error handle to
    "FromChildErrWriteHandle"
     7. Create the child process, ensuring that the handles are
    inherited
     8. Restore our standard handles
     9. Wait for the child to quit.
     10. Read from the output and error pipes.
     11. Close pipe handles.
    }
    MonitorChild:=false;
    CommandLine:=StrAlloc(256);
    PInputHost:=StrAlloc(256);
    ApplicationName:=nil;
    StrPCopy(CommandLine,'C:\WINDOWS\TRACERT.EXE');
    StrPCopy(PInputHost,InputHost);
    StrCat(CommandLine,PInputHost);
    with SecurityAttributes do
    begin
     nlength:=SizeOf(TSecurityAttributes);
     lpSecurityDescriptor:=nil;
     bInheritHandle:=true;
    end;
    {1}
    if
    CreatePipe(ToChildReadHandle,ToChildWriteHandle,@SecurityAttributes,4096)
    then
    begin
     if
    CreatePipe(FromChildReadHandle,FromChildWriteHandle,@SecurityAttributes,4096)
    then
     begin
     {Cool. The pipes are set up ... do stuff}
     {Now save our standard handles}
     SavedStdIn:=GetStdHandle(STD_INPUT_HANDLE);
     SavedStdOut:=GetStdHandle(STD_OUTPUT_HANDLE);
     {Now redirect our standard handles}
     SetStdHandle(STD_INPUT_HANDLE,ToChildReadHandle);
     SetStdHandle(STD_OUTPUT_HANDLE,FromChildWriteHandle);
     {Now create the child process}
     with StartupInfo do
     begin
     cb:=SizeOf(StartupInfo);
     lpReserved:=nil;
     lpDesktop:=nil;
     lpTitle:=nil;
     dwX:=0;
     dwY:=0;
     dwXCountChars:=0;
     dwYCountChars:=0;
     dwFillAttribute:=0;
     dwFlags:=STARTF_USESHOWWINDOW;
     cbReserved2:=0;
     lpReserved2:=nil;
     wShowWindow:=SW_MINIMIZE;
     end;
     if
    CreateProcess(ApplicationName,CommandLine,nil,nil,true,0,nil,nil,StartupInfo,ProcessInformation)
    then
     MonitorChild:=true
     else
     ErrorCode:=GetLastError;
     {Okay. Now reset our standard handles}
     SetStdHandle(STD_INPUT_HANDLE,SavedStdIn);
     SetStdHandle(STD_OUTPUT_HANDLE,SavedStdOut);
     {Now we can do what we want whilst the child process does it's
    stuff}
     if MonitorChild then
     begin
     WaitForSingleObject(ProcessInformation.hProcess,INFINITE);
     {Close input handles}
     CloseHandle(ToChildWriteHandle);
     CloseHandle(ToChildReadHandle);
     {At which point we now check that we have read all the data
    we can}
     {Close the write handle before trying to read.}
     CloseHandle(FromChildWriteHandle);
     repeat
    
    ReadOK:=ReadFile(FromChildReadHandle,ReadBuffer,16,BytesRead,nil);
     ErrorCode:=GetLastError;
     if BytesRead>0 then
     TraceOutput.WriteBuffer(ReadBuffer,BytesRead);
     until (BytesRead=0) or (not(ReadOK)) or
    (ErrorCode<>NO_ERROR);
     CloseHandle(FromChildReadHandle);
     {And similarly, read all the possible error messages}
     end
     else
     begin
     CloseHandle(FromChildReadHandle);
     CloseHandle(FromChildWriteHandle);
     CloseHandle(ToChildReadHandle);
     CloseHandle(ToChildWriteHandle);
     end;
     PostMessage(MainFrm.Handle,WM_FINISHED_ROUTING,0,0);
     end;
    end;
    StrDispose(CommandLine);
    StrDispose(PInputHost);
    end;


学习中请遵守法律法规,本网站内容均来自于互联网,本网站不负担法律责任
调用 D OS
#1楼
发帖时间:2016-7-9   |   查看数:0   |   回复数:0
游客组
快速回复