Possible Duplicate:
How to read from an external console application?
I have a third party console application
I want to execute it at run time form a delphi application.
on the execution
the console applications window must be hidden.and all the messages of the console application must be printed in a control of my application (Text box , memo etc)
and also using the control user must be able to input text.
Can anyone help me to do this
This will allow you to run and receive info back from a console (DOS-type) application into a TRichEdit. It doesn't allow you to input text once the app is running, but maybe it'll give you a starting point. (The original code is from a newsgroup post written by Dr. Peter Below of TeamB.)
procedure TFMainForm.RunDosInMemo(const App: String; AMemo: TRichEdit);
const
ReadBuffer = 2400;
var
Security : TSecurityAttributes;
StdInPipeR, StdInPipeW : THandle;
StdOutPipeR, StdOutPipeW : THandle;
StartInfo : TStartUpInfo;
ProcessInfo : TProcessInformation;
Buffer : PByte;
BytesAvailable, BytesRead : DWord;
sDosApp: String;
sData: RawByteString;
begin
sDosApp := DosApp;
UniqueString(sDosApp);
with Security do begin
nLength := SizeOf(TSecurityAttributes);
bInheritHandle := True;
lpSecurityDescriptor := nil;
end;
if CreatePipe(StdInPipeR, StdInPipeW, @Security, 0) then
try
SetHandleInformation(StdInPipeW, HANDLE_FLAG_INHERIT, 0);
if CreatePipe(StdOutPipeR, StdOutPipeW, @Security, 0) then
try
SetHandleInformation(StdOutPipeR, HANDLE_FLAG_INHERIT, 0);
GetMem(Buffer, ReadBuffer);
try
ZeroMemory(@StartInfo, SizeOf(StartInfo));
StartInfo.cb := SizeOf(StartInfo);
StartInfo.hStdOutput := StdOutPipeW;
StartInfo.hStdInput := StdInPipeR;
StartInfo.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
StartInfo.wShowWindow := SW_HIDE;
if CreateProcess(nil,
PChar(sDosApp),
nil,
nil,
True,
NORMAL_PRIORITY_CLASS,
nil,
nil,
StartInfo,
ProcessInfo) then
try
while WaitForSingleObject(ProcessInfo.hProcess, 500) <> WAIT_TIMEOUT do
Application.ProcessMessages;
while PeekNamedPipe(StdOutPipeR, nil, 0, nil, BytesAvailable, nil) do
begin
if BytesAvailable < 1 then
Break;
if BytesAvailable > ReadBuffer then
BytesAvailable := ReadBuffer;
if not ReadFile(StdOutPipeR,
Buffer[0],
BytesAvailable,
BytesRead,
nil) then
Break;
SetString(sData, PAnsiChar(Buffer), BytesRead);
// assign an appropriate codepage for the output data:
// 0 for default Ansi, 1252 or 20157 for ASCII, 1200 for
// Unicode, etc...
SetCodePage(sData, ...);
// this is faster and more efficient than reading/writing the
// Text property directly...
AMemo.SelStart := AMemo.GetTextLen;
AMemo.SelLength := 0;
AMemo.SelText := sData;
end;
finally
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
end;
finally
FreeMem(Buffer);
end;
finally
CloseHandle(StdOutPipeR);
CloseHandle(StdOutPipeW);
end;
finally
CloseHandle(StdInPipeR);
CloseHandle(StdInPipeW);
end;
end;
See this answer and this one.
Zarko wrote about this on Delphi.about.com.
This is a common requirement, for example, in IDEs and build tools, or apps which spawn external command line tools to do version control, for example.
To make the answer two-way, as you ask for it to be, is very complex, and I am not aware of anybody who has implemented a "command shell" or "terminal mode" completely in delphi.
I ported Zlatko's code to Delphi XE (also works in 2010) here.
精彩评论