如何调用DOS程序,并取得该程序的运行结果输出
编号:QA004722
建立日期: 2003年10月13日 最后修改日期:2003年10月13日
所属类别:
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;
相关问题:
QA001105 "如何将其它应用程序的运行过程在窗口内进行显示"
QA004729 "如何取得DOS程序的运行结果输出"
此问题由李海回答。
附加关键字:编程, 源程序, programming, source code, Delphi, VCL, Borland, Windows API, win32, api, windows api, gdi32, kernel。
| |
|
|
| |
|
|