开发者

embedded console applications in Delphi [duplicate]

开发者 https://www.devze.com 2023-02-19 06:57 出处:网络
Thi开发者_如何学Cs question already has answers here: Closed 11 years ago. Possible Duplicate: How to read from an external console application?
Thi开发者_如何学Cs question already has answers here: Closed 11 years ago.

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消