Home » Tipps & Tricks » System » Prozesse » Ausgabe der Konsole in meinem Programm anzeigen

Ausgabe der Konsole in meinem Programm anzeigen

Es ist möglich, aus Delphi heraus einen Kommandozeilenbefehl auszuführen und die Ausgabe, die normalerweise in DOS- bzw. Eingabezeilenfenster erscheint, abzufangen und in einer Stringliste zu speichern.Zentraler Befehl dieses Codes ist CreateProcess. Dieser Win32-API-Befehl erlaubt es, eine Anwendung so detailliert zu starten, dass auch die Ausgabe konfiguriert werden kann (über die Parameter-Struktur StartupInfo). Sie wird hier in eine Pipe (eine Art Datenröhre) umgeleitet, auf die im Beispiel über PipeOutputWrite zugegriffen wird. PipeOutputRead dient anschließend dazu, die dort aufgelaufenen Daten auszulesen und in einen Stream zu schreiben.

function GetConsoleOutput(Command : string;
                          Output, Errors : TStringList) : Boolean;
var
  Buffer            : array[0..255] of Char;
  CreationFlags     : DWORD;
  NumberOfBytesRead : DWORD;
  PipeErrorsRead    : THandle;
  PipeErrorsWrite   : THandle;
  PipeOutputRead    : THandle;
  PipeOutputWrite   : THandle;
  ProcessInfo       : TProcessInformation;
  SecurityAttr      : TSecurityAttributes;
  StartupInfo       : TStartupInfo;
  Stream            : TMemoryStream;
begin
  //Initialisierung ProcessInfo
  FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);

  //Initialisierung SecurityAttr
  FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
  SecurityAttr.nLength              := SizeOf(TSecurityAttributes);
  SecurityAttr.bInheritHandle       := True;
  SecurityAttr.lpSecurityDescriptor := nil;

  //Pipes erzeugen
  CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);
  CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);

  //Initialisierung StartupInfo
  FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  StartupInfo.cb          := SizeOf(TStartupInfo);
  StartupInfo.hStdInput   := 0;
  StartupInfo.hStdOutput  := PipeOutputWrite;
  StartupInfo.hStdError   := PipeErrorsWrite;
  StartupInfo.wShowWindow := SW_HIDE;
  StartupInfo.dwFlags     := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;

  CreationFlags := CREATE_DEFAULT_ERROR_MODE or
                   CREATE_NEW_CONSOLE or
                   NORMAL_PRIORITY_CLASS;

  // Folgende Zeile ist nur für Delphi ab 2009 erforderlich:
  UniqueString(Command);

  if CreateProcess(nil,
                   PChar(Command),
                   nil,
                   nil,
                   True,
                   CreationFlags,
                   nil,
                   nil,
                   StartupInfo,
                   ProcessInfo) then
  begin
    Result := True;
    //Write-Pipes schließen
    CloseHandle(PipeOutputWrite);
    CloseHandle(PipeErrorsWrite);

    //Ausgabe Read-Pipe auslesen
    Stream := TMemoryStream.Create;
    try
      while ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil) do
      begin
        Stream.Write(Buffer, NumberOfBytesRead);
      end;
      Stream.Position := 0;
      Output.LoadFromStream(Stream);
    finally
      Stream.Free;
    end;
    CloseHandle(PipeOutputRead);

    //Fehler Read-Pipe auslesen
    Stream := TMemoryStream.Create;
    try
      while ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil) do
      begin
        Stream.Write(Buffer, NumberOfBytesRead);
      end;
      Stream.Position := 0;
      Errors.LoadFromStream(Stream);
    finally
      Stream.Free;
    end;
    CloseHandle(PipeErrorsRead);

    WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
    CloseHandle(ProcessInfo.hProcess);
  end
  else
  begin
    Result := False;
    CloseHandle(PipeOutputRead);
    CloseHandle(PipeOutputWrite);
    CloseHandle(PipeErrorsRead);
    CloseHandle(PipeErrorsWrite);
  end;
end;

Aufrufbeispiel:
Für die Ausgabe und die Fehler wird zunächst eine Stringliste erzeugt. Anschließend wird obige Funktion aufgerufen. Wurde sie erfolgreich ausgeführt (Rückgabewert ist True), wird die Output-Stringliste in einem Memo angezeigt.Um Kommandozeilenbefehle ausführen zu können, die keine eigenständigen Anwendungen sind (wie der DOS-Befehl „dir“ im folgenden Beispiel), muss der Name des Kommandozeileninterpreters davor stehen. „cmd.exe“ ist das unter Windows NT/2000/XP und „command.com“ unter Windows 9x. Der Parameter /c sorgt dafür, dass der Kommandozeilenbefehl ausgeführt und die Kommandozeile anschließend wieder geschlossen wird.

procedure TForm1.Button1Click(Sender: TObject);
var 
  Output : TStringList;
  Errors : TStringList;
begin
  Output := TStringList.Create;
  Errors := TStringList.Create;
  try
    if GetConsoleOutput('cmd /c dir c:', Output, Errors) then
      Memo1.Lines.AddStrings(Output);
  finally
    Output.free;
    Errors.free;
  end;
end;

Ein Gedanke zu „Ausgabe der Konsole in meinem Programm anzeigen“

  1. Vielen Dank für das Beispiel! Das war genau das, was ich gesucht habe. Funktionierte auf Anhieb.

Kommentare sind geschlossen.