I'd like to create some kind of command prompt, embedded in my project's form. I use
CmdLine package (with TCmdBox component) and I run the process with TProcess. I use example given
here as the skeleton. Since I want the process to be interactive, I can't just buffer everything and flush it once in the end. That wouldn't make sense when the process has this kind of statement:
...
Write('What''s your name?');
ReadLn(Name);
...
The question won't be displayed while ReadLn stays blocking, users might even think that a deadlock has occured. Anyway, here's the complete code (without input processing):
procedure TMainForm.CmdBoxInput(ACmdBox: TCmdBox; InputStr: String);
const
READ_BYTES = 2048;
var
CmdProcess: TProcess;
MemStr: TMemoryStream;
StrList: TStringList;
n: Integer;
ErrMsg: PChar;
begin
try
CmdProcess:=TProcess.Create(nil);
MemStr:=TMemoryStream.Create;
StrList:=TStringList.Create;
MemStr.SetSize(READ_BYTES);
with CmdProcess do begin
CommandLine:=InputStr;
Options:=[poUsePipes,poStderrToOutPut];
ShowWindow:=swoHide;
Execute;
while Running do begin
n:=Output.Read(MemStr.Memory^,READ_BYTES);
if n>0 then begin
StrList.LoadFromStream(MemStr);
CmdBox.Write(StrList.Text); // CmdBox.WriteStream causes Access Violation
MemStr.Clear;
end else
Sleep(100);
end;
end;
except
on e: EProcess do begin
{$IFDEF Windows}
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM,
nil,GetLastError,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
@ErrMsg,0,nil
);
{$ELSE}
ErrMsg:=@e.Message[1];
{$ENDIF}
CmdBox.WriteLn(ErrMsg);
SetCmdBoxPrompt(FPath+'>');
Exit;
end;
on e: Exception do begin
MessageDlg('Error',e.Message,mtError,[mbOK],0);
Exit;
end;
end;
repeat
n:=CmdProcess.Output.Read(MemStr.Memory^,READ_BYTES);
if n>0 then CmdBox.WriteStream(MemStr);
until n<=0;
StrList.Free;
MemStr.Free;
CmdProcess.Free;
SetCmdBoxPrompt(FPath+'>');
end;
But it fails for any program that requires interaction or has large output. I don't really know how to use TMemoryStream and only know a common use of TProcess, perhaps I misunderstood something here.