Delphi中的嵌入式控制台应用程序

时间:2011-03-24 16:11:40

标签: delphi console

  

可能重复:
  How to read from an external console application?

我有第三方控制台应用程序

我想在运行时从delphi应用程序执行它。

执行

必须隐藏控制台应用程序窗口。控制台应用程序的所有消息必须打印在我的应用程序的控件中(文本框,备忘录等)

并且还使用控件用户必须能够输入文本。

任何人都可以帮我这样做

2 个答案:

答案 0 :(得分:3)

这将允许您从控制台(DOS类型)应用程序运行和接收信息到TRichEdit。一旦应用程序运行,它不允许您输入文本,但它可能会给您一个起点。 (原始代码来自TeamB的Peter Below博士撰写的新闻组帖子。)

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;

答案 1 :(得分:0)

请参阅此answerthis一个。

Zarko在Delphi.about.com上写到了这一点。

这是一个常见的要求,例如,在IDE和构建工具中,或者产生外部命令行工具来进行版本控制的应用程序,例如。

如你要求的那样双向回答是非常复杂的,我不知道有任何人在delphi中完全实现了“命令shell”或“终端模式”。

我将Zlatko的代码移植到Delphi XE(也适用于2010年)here