Announcement

Collapse
No announcement yet.

Stdout und Stderr umleiten

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Stdout und Stderr umleiten

    Hallo,

    mit folgender kleinen Funktion leite ich stdout und stderr eines mittels CreateProcess gestarteten Child Process um, um die Ausgabe in einem Memofeld anzuzeigen. Das klappt auch bei allen Programmen mit denen ich getestet habe, außer bei xcopy.exe. Xcopy.exe wird zwar gestartet und liefert als Exitcode 0, aber das Programm gibt nichts aus und kopiert auch keine Dateien. Kann mir hierzu jemand einen Tipp geben?

    procedure TForm1.BtnChildWindowsClick(Sender: TObject);<br>
    const<br>
    kProcess = 'xcopy.exe';<br>
    kMaxLine = 128;<br>
    var<br>
    PipeRead: THandle;<br>
    PipeWrite: THandle;<br>
    ReadTmp: THandle;<br>
    ParentProcess: THandle;<br>
    si: TStartupInfo;<br>
    pi: TProcessInformation;<br>
    sc: TSecurityAttributes;<br>
    sLine: array[1..kMaxLine] of Char;<br>
    dwBytesRead: DWord;<br>
    dwExitCode: DWord;v
    begin<br>
    // Security Descriptor aufbauen und eine Unnamed Pipe<br>
    // erzeugen. Die Handles für Read/Write sollen vererbbar<br>
    // sein.<br>
    with sc do<br>
    begin<br>
    nLength := SizeOf(sc);<br>
    bInheritHandle := True;<br>
    lpSecurityDescriptor := nil;<br>
    end;<br>
    Win32Check(CreatePipe(PipeRead, PipeWrite, @sc, 0));<br>

    // Read Handle der Pipe soll nicht vererbt werden, daher ein<br>
    // Duplikat anfertigen, dass nicht vererbbar ist. Der später<br>
    // erzeuge Child Process soll nur in die Pipe schreiben.<br>
    ParentProcess := GetCurrentProcess;<br>
    Win32Check(DuplicateHandle(ParentProcess, PipeRead, ParentProcess,<br>
    @ReadTmp, 0, False, DUPLICATE_SAME_ACCESS));<br>
    CloseHandle(PipeRead);<br>
    PipeRead := ReadTmp;<br>

    // Child Process starten. Das Write Handle wird stdout und stderr.<br>
    // Zusätzlich wird das Fenster versteckt.<br>
    GetStartupInfo(si);<br>
    with si do<br>
    begin<br>
    dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;<br>
    hStdOutput := PipeWrite;<br>
    hStdError := PipeWrite;<br>
    wShowWindow := SW_HIDE;<br>
    end;<br>
    Win32Check(CreateProcess(nil, PChar(kProcess), nil, nil,<br>
    True, 0, nil, nil, si, pi));<br>

    // Handle wird nicht mehr benötigt und muss hier sofort<br>
    // geschlossen werden, sonst blockiert ReadFile, weil das<br>
    // Handle noch gültig ist.<br>
    CloseHandle(PipeWrite);<br>

    MemOutput.Text := '';<br>
    ZeroMemory(@sLine, kMaxLine);<br>
    while ReadFile(PipeRead, sLine, kMaxLine, dwBytesRead, nil) do<br>
    begin<br>
    MemOutput.Text := MemOutput.Text + sLine;<br>
    Application.ProcessMessages;<br>
    ZeroMemory(@sLine, kMaxLine);<br>
    end;<br>

    Win32Check(GetExitCodeProcess(pi.hProcess, dwExitCode));<br>
    if dwExitCode <> 0 then<br>
    begin<br>
    MemOutput.Text := MemOutput.Text + #13#10 + 'Exit:' + IntToStr(dwExitCode);<br>
    end;<br>

    // Die Handles für Prozess und Thread werden nicht benötigt.<br>
    CloseHandle(pi.hProcess);<br>
    CloseHandle(pi.hThread);<br>
    end;<br>

    Vielen Dank schon mal,<br>
    Carsten
Working...
X