Announcement

Collapse
No announcement yet.

DOS-Programmausgabe abfangen...

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

  • Matthias Heim
    started a topic DOS-Programmausgabe abfangen...

    DOS-Programmausgabe abfangen...

    Hallo zusammen
    Ich bin noch ganz neu hier in der Delphi-Welt. Aber ich habe schon viele Erfahrungen in Turbo-Pascal. Nun möchte ich mein Programm, welches das Handling von parameterorientierten Programmen regelte neu für Windows programmieren. Unter DOS habe ich die Ausgabe des "fremden" Programms einfach abgefangen indem ich den Interrupt 29 umbog (Mit Getintvec und Setintvec, falls das jem. interessiert) und die Daten in einen Texteditor umleitete. Unter Delphi geht das aber nicht mehr. Trotzdem möchte ich aber die Bildschirmausgaben irgendwie abfangen und in ein Edit-Fenster kriegen. Kann mir jemand sagen, wie das geht?

  • Matthias Heim
    replied
    Hallo

    Ich habe gesehen, dass man bei CreateProcess über Startupinformationen auch einen Parameter "Handle Stdoutput" übergeben kann. Ist es nicht auch möglich, die Daten über dieses Handle abzuleiten. Wenn ja, wie?

    MfG Matthia

    Leave a comment:


  • Matthias Heim
    replied
    Sorry für die fürchterliche Formatierung. (Bin selbst erschrocken). Aber ich kann kein Wort HTML (Eine Bildungslücke, ich weiss).
    Unter "Entwickler Forum/Betriebssysteme/Win32/fehlermeldungen im dosfenster ausdrucken!!" findet ihr den Quelltext besser formatiert.

    Matthia

    Leave a comment:


  • Matthias Heim
    replied
    Hallo

    Jetzt habe ich das ganze mit ReadConsoleOutput probiert. Scheint aber, dass ich doch auf noch zu wackligen Delphi-Füssen stehe.
    Obwohl ich den vordefinierten Code, den ich im Entwicklerforum unter "Betriebssysteme/Win32/Fehlermeldungen im Dosfenster ausdrucken" benutzte, kriegte ich das nicht hin.
    Unten noch einmal der Code für Interessierte (von Andreas Kosch, 01:40pm Nov 15, 1999 GMT):
    Zuerst aber zu meinem neuen Problem, auch nachdem ich "pcInfo" durch "PCharInfo" ersetzte, und alle "btnGrab:=..." entfernte (Kann mir jemand den Sinn dieser Variable erklären?) kriegte ich doch noch jedesmal wenn ich das Programm aufrief einen Speicherzugrifffehler bei der zweiten FOR-Schleife ( sLineBuff := sLineBuff + pGrabBuff^[i * X + j].AsciiChar; ). Wahrscheinlich wurde vorher die Consolenfenstergrösse falsch ermittelt(?). Und so sehr ich mich auch durch die Online-Hilfe schlängle, ich krieg den Fehler nicht raus. Wie krieg ich die Ausgabe von ReadConsoleOutput in ein Memo rein?
    Ach übrigens, was passiert, wenn der Output des Programms länger als die üblichen 25 Consolenzeilen ist?

    MfG Matthias Heim

    Hier nun der Code der von mit benutzten Procedure:

    procedure TFormMain.btnGrabClick(Sender: TObject);
    var
    aDest : TCoord;
    aCSBI : TConsoleScreenBufferInfo;
    i, j : integer;
    sLineBuff : String;
    szOemChar : array[0..254] of Char;
    pGrabBuff : pcInfo;
    begin
    btnGrab.Enabled := False;
    aDest.X := 0;
    aDest.Y := 0;
    try
    // Eigenschaften (Breite+Höhe) des Consolenfensters auslesen
    GetConsoleScreenBufferInfo(hConsole, aCSBI);
    // Platz für den Zeilenpuffer reservieren
    SetLength(sLineBuff, aCSBI.dwMaximumWindowSize.X + 1);
    // Platz für den Consolenpuffer reservieren
    // (= Breite * Höhe * Größe von TCharInfo)
    with aCSBI.dwMaximumWindowSize do
    GetMem(pGrabBuff, X * Y * SizeOf(TCharInfo));
    try
    // Inhalt des Consolen-Fensters in den Puffer einlesen
    with aCSBI do
    ReadConsoleOutput(hConsole, pGrabBuff,
    dwMaximumWindowSize, aDest, srWindow);
    // Daten aus dem Puffer in die TMemo-Instanz einsetzen
    Memo1.Clear;
    with aCSBI.dwMaximumWindowSize do begin
    // Inhalt des Consolenfensters Zeilenweise auslesen
    for i := 0 to Y - 1 do begin
    // Zeilenpuffer leeren
    sLineBuff := '';
    // alle Zeichen dieser Zeile in den Zeilenpuffer kopieren
    for j := 1 to X do
    sLineBuff := sLineBuff + pGrabBuff^[i * X + j].AsciiChar;
    // Zeichensatz (OEM) nach ANSI konvertieren
    OemToChar(PChar(sLineBuff), szOemChar);
    // gefüllten Zeilenpuffer in die TMemo-Instanz einsetzen
    Memo1.Lines.Add(szOemChar);
    end;
    end;
    StatBar.Panels[1].Text := Format('%d x %d Zeichen',
    [aCSBI.dwMaximumWindowSize.X,
    aCSBI.dwMaximumWindowSize.Y]);
    finally
    Freemem(pGrabBuff);
    end;
    finally
    btnGrab.Enabled := true;
    end;
    end

    Leave a comment:


  • Andreas Kosch
    replied
    Hallo,

    zuerst zur letzten Frage: Ein echtes Verstecken über SW_HIDE ist nicht notwendig, es reicht doch völlig aus, das Fenster über <b>SetWindowPos</b> aus dem sichtbaren Bereich des Desktops hinauszuschlieben (negative Koordinaten). Somit ist es für den Benutzer "unsichtbar".
    Anstelle von <b>WinExec</b> (alte "16-Bit-Funktion") würde ich das 32-Bit-Gegenstück <b>CreateProcess</b> verwenden:

    <pre>

    var
    hConsole : THandle;
    aPI : TProcessInformation;
    hWndPrg : hWnd;
    ...
    // neue Console für diesen Prozess anfordern
    if AllocConsole then
    begin
    StrPCopy(szAppName, EditPrg.Text);
    // TStartupInfo-Datenstruktur initialisieren
    FillChar(aSI, Sizeof(aSI), #0);
    with aSI do begin
    cb := Sizeof(aSI);
    dwFlags := STARTF_USESHOWWINDOW;
    wShowWindow := SW_SHOWDEFAULT;
    end;
    // Programm als neuen Process starten
    if CreateProcess(nil, szAppName, nil, nil, False,
    CREATE_SEPARATE_WOW_VDM or NORMAL_PRIORITY_CLASS,
    nil, nil, aSI, aPI) then
    begin
    // Überschrift des Consolen-Fensters setzen
    SetConsoleTitle(PChar(cTITEL));
    // Handle für den Standard-Output der Console holen
    hConsole := GetStdHandle(STD_OUTPUT_HANDLE);
    ...
    end
    </pre>

    Über <b>ReadConsoleOutput(hConsole,...)</b> wird das in hConsole abgelegte Handle verwendet. Falls das Fensterhandle gesucht wird, hilft der folgende Aufruf weiter:
    <pre>
    var
    szTitel : array[0..254] of Char;
    begin
    // Consolen-Fensterzeilenbeschriftung auslesen
    GetConsoleTitle(szTitel, SizeOf(szTitel));
    // Fensterhandle suchen
    hWndFUSIN := FindWindow(nil, szTitel);
    </pre&gt

    Leave a comment:


  • Matthias Heim
    replied
    Hallo Herr Kosch

    Vielen Dank für die prompte Reaktion. Die Standard-Ausgabe umzuleiten ist nicht möglich, da ich nicht für alle Programme, die kontrolliert werden sollen den Code habe, also muss ich ReadConsoleOutput verwenden. Aber wie krieg ich das Handle der Anwendung raus, wenn ich sie mit Winexec aufrufe. Funktioniert das auch, wenn ich das Programm mit sw_hide im Hintergrund aufrufe ( WINEXEC(@Programm[1],sw_hide) ) ?

    Matthias Hei

    Leave a comment:


  • Andreas Kosch
    replied
    Hallo,

    wenn eine <b>Consolen</b>-Anwendung (32-Bit-Programm, das ohne grafische Benutzeroberfläche im Fenster der <i>Eingabeaufforderung</i> ausgeführt wird) entwickelt werden soll, gibt es für diese Aufgabe mehrere Alternativen. <br>
    a) Die Consolenanwendung leitet die <b>Standard-Ausgabe</b> (StdOut) um, so das ein anderes Programm die Ausgabe der Consolenanwendung direkt übernehmen kann. <br>
    b) Ein anderes Programm liest ständig über den Aufruf der Win32-APPI-Funktion <b>ReadConsoleOutput</b> den Inhalt des aktuellen Consolenfensters aus. Dies ist auch dann erfolgreich, wenn StdOut nicht gesondert von der Consolenanwendung gesetzt wird.

    Beispiel für beide Fälle finden sich in meinem neuen (demnächst erscheinenden) Buch <b>Delphi Win32-Lösungen</b>

    Leave a comment:

Working...
X