AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi CMD-Ausgabe von chkdsk, wget usw. ordentlich?
Thema durchsuchen
Ansicht
Themen-Optionen

CMD-Ausgabe von chkdsk, wget usw. ordentlich?

Ein Thema von Dalai · begonnen am 1. Jun 2009 · letzter Beitrag vom 2. Jun 2009
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.682 Beiträge
 
Delphi 5 Professional
 
#1

CMD-Ausgabe von chkdsk, wget usw. ordentlich?

  Alt 1. Jun 2009, 18:00
Hallo Forum,

bitte nicht hauen, wenn ich das falsche Unterforum erwischt haben sollte, denn wie ihr seht, schreibe ich zum ersten Mal hier in der DP . Ich fand dies das passendste Unterforum.

Ich weiß, dass DOS-Ausgaben usw. schon mehrfach behandelt wurden, aber ich habe ein spezielleres Problem.

Ich habe eine Klasse TLaunch, die versch. Eigenschaften und VCL-Objekte (z.B. einen Button) beinhaltet. Beim Klick auf diesen Button wird der in den Eigenschaften des Objekts gespeicherte Befehl ausgeführt, und zwar unter Verwendung dieser Methode:
Delphi-Quellcode:
procedure TMainForm.LaunchClick(Sender: TObject);
const BufSize = 1024;
var
    // Ausführung mit Capture
    SA: TSecurityAttributes;
    SI: TStartupInfo;
    PI: TProcessInformation;
    StdOutPipeRead, StdOutPipeWrite: THandle;
    WasOK: Boolean;
    Buffer: array[0..BufSize] of Char;
    BytesRead: Cardinal;
begin
    obj:= (Sender as TLaunch);
    LogForm.LogMemo.Clear;
    LogForm.CloseBtn.Enabled:= False;
    LogForm.MyShowModal;
    with SA do
    begin
        nLength:= SizeOf(SA);
        bInheritHandle:= True;
        lpSecurityDescriptor:= nil;
    end;
    try
        CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
        Application.ProcessMessages;
        with SI do
        begin
            FillChar(SI, SizeOf(SI), 0);
            cb:= SizeOf(SI);
            dwFlags:= STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
            wShowWindow:= SW_HIDE;
            hStdInput:= GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
            hStdOutput:= StdOutPipeWrite;
            hStdError:= StdOutPipeWrite;
        end;
        WasOK:= CreateProcess(nil, PChar(obj.ExecFile + ' ' + obj.ExecParams),
                           nil, nil, True, 0, nil,
                           PChar(obj.ExecWorkDir),
                           SI, PI);
        CloseHandle(StdOutPipeWrite);
        if WasOK then
          try
            Application.ProcessMessages;
            repeat
                Application.ProcessMessages;
                WasOK:= ReadFile(StdOutPipeRead, Buffer, Pred(BufSize), BytesRead, nil);
                if BytesRead > 0 then
                begin
                    Buffer[BytesRead]:= #0;
                    OemToChar(Buffer, Buffer);
                    LogForm.LogMemo.Text:= LogForm.LogMemo.Text + String(Buffer);
                end;
                Sleep(50);
            until not WasOK or (BytesRead = 0);
            WaitForSingleObject(PI.hProcess, INFINITE);
          finally
            CloseHandle(PI.hThread);
            CloseHandle(PI.hProcess);
          end;
    finally
        CloseHandle(StdOutPipeRead);
        //CloseHandle(StdOutPipeWrite);
    end;
    LogForm.CloseBtn.Enabled:= True;
    LogForm.CloseBtn.SetFocus;
end;
Die Ausgabe wird auch wunderbar im Memo angezeigt, und das auch schön "in Echtzeit", also nicht erst nach Ende des Programms. Nun zum Problem: Programme, die Ausgaben in derselben Zeile erzeugen (chkdsk, wget, freshclam), generieren dann derartigen Output (gekürzt):
Code:
Der Typ des Dateisystems ist FAT32.
Datenträger SYSTEM erstellt 29.08.2006 00:34
Datenträgernummer: 44F3-8B85
Dateien und Ordner werden überprüft...
0 Prozent durchgeführt.
3 Prozent durchgeführt..
4 Prozent durchgeführt...
5 Prozent durchgeführt....
6 Prozent durchgeführt.....
7 Prozent durchgeführt......
8 Prozent durchgeführt.
9 Prozent durchgeführt..
10 Prozent durchgeführt...
11 Prozent durchgeführt....
12 Prozent durchgeführt.....
13 Prozent durchgeführt......
14 Prozent durchgeführt.
15 Prozent durchgeführt..
16 Prozent durchgeführt...
17 Prozent durchgeführt....
18 Prozent durchgeführt.....
19 Prozent durchgeführt......
Allerdings stehen die Prozentangaben alle in einer Zeile, die dann vom Memo irgendwann umgebrochen werden (bei maximaler Stringlänge oder so).

Hat jemand eine Idee, wie ich wirklich nur die Zeilen bekomme, die man auch sieht, wenn man die Befehle in der CMD ausführen würde?

Danke im Voraus für Hilfe

MfG Dalai
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: CMD-Ausgabe von chkdsk, wget usw. ordentlich?

  Alt 1. Jun 2009, 18:07
Du meinst, dass das in der selben Zeile aktualisiert wird?

Das wirst du manuell machen müssen, weil diese Positionierungsbefehle nicht mit angefangen werden. Ich weiß nicht, ob man das auch richtig hinbekommt. :nixweiss:
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.682 Beiträge
 
Delphi 5 Professional
 
#3

Re: CMD-Ausgabe von chkdsk, wget usw. ordentlich?

  Alt 1. Jun 2009, 18:17
Zitat von jaenicke:
Du meinst, dass das in der selben Zeile aktualisiert wird?
So weit muss es nicht zwingend gehen. Es würde mir (vorerst) genügen, wenn die Ausgaben wie oben sind (alles untereinander) statt alles in derselben Zeile...

Zitat von jaenicke:
Das wirst du manuell machen müssen, weil diese Positionierungsbefehle nicht mit angefangen werden.
Hast du eine Idee, wie ich das machen könnte? OK, eine Suche nach Chr(13) und/oder Chr(10) kann helfen, aber ob das genügt? Denn was ist, wenn die Zeichen mitten im String gefunden werden?

MfG Dalai
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: CMD-Ausgabe von chkdsk, wget usw. ordentlich?

  Alt 1. Jun 2009, 18:21
Ach jetzt verstehe ich. Ja, warum legst du es denn einfach hintereinander in das Memo, wenn du das gar nicht willst? Dann füge es doch in eine neue Zeile hinzu.LogForm.LogMemo.Lines.Add(String(Buffer)); Besser wäre aber vermutlich einfach eine Komponente wie TDosCommand, dann musst du nicht die Ausgabe ins Memo in die Logik der Ausführung des Befehls bringen...
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.682 Beiträge
 
Delphi 5 Professional
 
#5

Re: CMD-Ausgabe von chkdsk, wget usw. ordentlich?

  Alt 1. Jun 2009, 18:34
Lines.Add() ist zwar schön, aber das erzeugt einen noch viel zerrupfteren Output. Wenn ich das Sleep(50) komplett rausnehme, werden auch einzelne Zeichen, die der Befehl ausgibt, auf eine neue Zeile geschrieben. Reduziere ich nur die Schlafzeit, landen trotzdem noch Zeilen hintereinander...

Zitat von jaenicke:
Besser wäre aber vermutlich einfach eine Komponente wie TDosCommand
Darüber bin ich auch schon gestolpert. Ob das was für den Fall geeignet ist, weiß ich noch nicht, werde ich aber testen.

Zitat von jaenicke:
dann musst du nicht die Ausgabe ins Memo in die Logik der Ausführung des Befehls bringen...
Das ist egal, weil das alles der Ereignisbehandlung des Klicks auf den Button dient.

MfG Dalai
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#6

Re: CMD-Ausgabe von chkdsk, wget usw. ordentlich?

  Alt 1. Jun 2009, 18:36
Zitat von Dalai:
Lines.Add() ist zwar schön, aber das erzeugt einen noch viel zerrupfteren Output.
Ja, stimmt, weil das eben nicht bis zum Zeilenende wartet. Was bei dem Quelltext auch egal ist, weil der für die Auswertung am Ende gedacht war.

TDosCommand hingegen bietet dir ein Event für eine neue Zeile an oder schreibt auf Wunsch das ganze gleich direkt in ein Memo.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#7

Re: CMD-Ausgabe von chkdsk, wget usw. ordentlich?

  Alt 1. Jun 2009, 18:44
Ich habe arge Zweifel, ob das mit dem aktuellen Ansatz überhaupt geht. Vermutlich verwenden die Programme die "low-level" Konsolenfunktionen, die ziemlich schwierig abzufangen sind. Da müsstest du dich mal einsehen, wie man MSDN-Library durchsuchenReadConsoleOutput verwendet.
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.682 Beiträge
 
Delphi 5 Professional
 
#8

Re: CMD-Ausgabe von chkdsk, wget usw. ordentlich?

  Alt 1. Jun 2009, 19:44
Zitat von Apollonius:
Ich habe arge Zweifel, ob das mit dem aktuellen Ansatz überhaupt geht.
Das habe ich auch befürchtet.

TDosCommand habe ich mir angeschaut und für brauchbar befunden. Ich habe den Klassen TDosThread und TDosCommand noch 2 weitere Attribute hinzugefügt: FConvert für die Konvertierung nach ANSI und FWorkDir zum Setzen des Arbeitsverzeichnisses, denn manche Programme brauchen das.

Das Ergebnis ist ein schicker Output mit untereinanderliegenden Zeilen (so wie im ersten Post zu sehen) . Lustiger Nebeneffekt: chkdsk funktioniert jetzt auch auf meinem Hostsystem, was bei meiner Variante nicht der Fall war . Keine Ahnung, wo das Problem war, auf anderen Rechnern wurde die Ausgabe problemlos abgefangen, nur auf dem einen nicht.

Das ReadConsoleOutput sieht mir zu kompliziert aus, und ich denke, mit dem jetzigen Stand kann ich ganz gut leben.

Danke für die schnelle Hilfe!

MfG Dalai
  Mit Zitat antworten Zitat
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.682 Beiträge
 
Delphi 5 Professional
 
#9

Re: CMD-Ausgabe von chkdsk, wget usw. ordentlich?

  Alt 2. Jun 2009, 01:15
Ich hoffe nochmals auf eure Hilfe .

Meine Änderung bzgl. Konvertierung in ANSI tut nicht so, wie ich das hoffte . In der Methode TDosThread.FExecute habe ich folgende Änderung vorgenommen (durch Kommentar markiert):
Delphi-Quellcode:
if (bread <> 0) then begin
  if (iBufSize < avail) then begin // If BufferSize too small then rezize
    iBufSize := avail;
    ReallocMem(pBuf, iBufSize);
  end;
  FillChar(pBuf^, iBufSize, #0); //empty the buffer
  ReadFile(read_stdout, pBuf^, iBufSize, bread, nil); //read the stdout pipe

  // --- Änderung
  if FConvert AND (bread > 0) then
      OemToChar(pBuf^, pBuf^);
  // --- Änderung

  Str := Last; //take the begin of the line (if exists)
  i := 0;
  while ((i < bread) and not (Terminated)) do begin
    case pBuf^[i] of
[...]
FConvert ist ein boolsches Attribut, was ich hinzugefügt habe.
Ein Rechner hat damit allerdings ein Problem und er beendet nicht nur das ausgeführte Konsolenprogramm sondern auch das Delphi-Prog sang- und klanglos. Meine Vermutung ist, dass die Variable pBuf^ nicht mit #0 abgeschlossen ist (in bestimmten Situationen) und OemToChar() deswegen ins Schlingern kommt.

Wie löse ich das mit möglichst wenig (Konvertierungs-)Aufwand?

MfG Dalai
  Mit Zitat antworten Zitat
Fridolin Walther

Registriert seit: 11. Mai 2008
Ort: Kühlungsborn
446 Beiträge
 
Delphi 2009 Professional
 
#10

Re: CMD-Ausgabe von chkdsk, wget usw. ordentlich?

  Alt 2. Jun 2009, 02:13
Delphi-Quellcode:
  // --- Änderung
  if FConvert AND (bread > 0) then
      OemToChar(pBuf^, pBuf^);
  // --- Änderung
Wieso dereferenzierst Du pBuf? OemToChar mag doch nen Pointer haben laut MSDN. Oder ist die Delphi Definition der Funktion mit var erfolgt?
Fridolin Walther
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:26 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz