AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Commandline-Tool in Delphi-Prog umleiten
Thema durchsuchen
Ansicht
Themen-Optionen

Commandline-Tool in Delphi-Prog umleiten

Ein Thema von Jörn · begonnen am 20. Jan 2004 · letzter Beitrag vom 21. Jan 2004
Antwort Antwort
Seite 1 von 2  1 2      
Jörn

Registriert seit: 5. Sep 2003
Ort: Helmstedt
312 Beiträge
 
#1

Commandline-Tool in Delphi-Prog umleiten

  Alt 20. Jan 2004, 17:12
Mit folgender Prozedur (nich mal von mir *gg*) leite ich die Ausgabe aus einem cmd-tool in ein memo um:

Delphi-Quellcode:
procedure CaptureDosCmd(command:String;OutputMemo:TMemo);
const
  CaptureBufferSize = 2500;
var
  SecAttrib : TSecurityAttributes;
  ReadPipe,writePipe : THandle;
  Startup : TStartUpInfo;
  ProcessInfo : TProcessInformation;
  CaptureBuffer : Pchar;
  BytesRead : DWord;
  WaitHandle : DWord;
begin
  OutPutMemo.Lines.clear;
  OutputMemo.lines.add('Starte "'+command+'"');
  With SecAttrib do
  begin
    nlength := SizeOf(TSecurityAttributes);
    binherithandle := true;
    lpsecuritydescriptor := nil;
  end;
  if Createpipe (ReadPipe, writePipe, @SecAttrib, 0) then
  begin
    CaptureBuffer := AllocMem(CaptureBufferSize + 1);
    FillChar(Startup,Sizeof(Startup),#0);
    Startup.cb := SizeOf(Startup);
    Startup.hStdOutput := writePipe;
    Startup.hStdInput := ReadPipe;
    Startup.dwFlags := STARTF_USESTDHANDLES +
                           STARTF_USESHOWWINDOW;
    Startup.wShowWindow := SW_HIDE;

    if CreateProcess(nil,
      PChar(command),
      @SecAttrib,
      @SecAttrib,
      true,
      NORMAL_PRIORITY_CLASS,
      nil,
      nil,
      Startup,
      ProcessInfo) then
    begin
      repeat
        WaitHandle := WaitForSingleObject( ProcessInfo.hProcess,100);
        Application.ProcessMessages;
      until (WaitHandle <> WAIT_TIMEOUT) or application.terminated;
      if not application.terminated then
      Repeat
        BytesRead := 0;
        ReadFile(ReadPipe,CaptureBuffer[0],CaptureBufferSize,BytesRead,nil);
        CaptureBuffer[BytesRead]:= #0;
        OemToAnsi(CaptureBuffer,CaptureBuffer);
        OutputMemo.Text := OutputMemo.Text+String(CaptureBuffer);
      until (BytesRead < CaptureBufferSize);
      end else OutPutMemo.lines.add('Operation wurde abgebrochen!');
    FreeMem(CaptureBuffer);
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(ReadPipe);
    CloseHandle(writePipe);
  end else OutPutMemo.lines.add('Konnte Kommando nicht starten, Fehler: #'+
  inttostr(getlasterror));
end;
Wenn ich etwas schnelles wie zB dir C:\ aufrufe, ist das auch gar kein Problem. Ich möchte aber einen alten cmd-Packer nutzen und dafür eine GUI schreiben. Doch bei solch "langen" Laufzeiten funktioniert das ganze nicht bzw man sieht den Fortschritt nicht weil

Delphi-Quellcode:
        repeat
        WaitHandle := WaitForSingleObject( ProcessInfo.hProcess,100);
        Application.ProcessMessages;
      until (WaitHandle <> WAIT_TIMEOUT) or application.terminated;
hier gewartet wird, bis das Programm beendet wird, dann wird der Inhalt des cmds in das Memo kopiert. Die 100 ist quasi der timeout (bin ich der Meinung). Alles was darüber hinausgeht, funktioniert daher nicht. Aufruf der Funktion wäre zB

CaptureDosCmd(cmd+' /c dir '+par,Memo1); Nun weiss ich aber nicht, wie ich erreichen kann, das entweder alles in "Echtzeit" in das Memo geschrieben wird, oder das nach einer beliebig langen Laufzeit das Memo gefüllt wird.

Ich hoffe ich habe das ausreichend erläutert. Schon mal vielen Dank für eure Hilfe

MfG
  Mit Zitat antworten Zitat
Jörn

Registriert seit: 5. Sep 2003
Ort: Helmstedt
312 Beiträge
 
#2

Re: Commandline-Tool in Delphi-Prog umleiten

  Alt 20. Jan 2004, 22:18
Minimallösung gefunden; ich kann in der funktion waitforsingleobject statt 100 INFINITE eintragen, dann würde das Prog schon mal laufen ohne abzuschmieren (in der Theorie natürlich). Leider hab ich dann immer noch keine Aktualisierung...
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#3

Re: Commandline-Tool in Delphi-Prog umleiten

  Alt 20. Jan 2004, 23:01
Da das auszuführende Programm sicherlich den Bildschirminhalt überschreibt (z.B. Prozentanzeige immer an der gleichen Stelle), wird eine Umleitung der Ausgabe in eine Pipe nicht ausreichen...
Es geht also eher darum, den Inhalt der Konsole mittels API-Funktionen komplett auszulesen. Das notwendige Konsolen-Handle hat man aber nur zur Verfügung, wenn selbige dem eigenen Prozess gehört. Es ist aber alles andere als einfach eine saubere Anwendung zu schreiben, die sowohl die GUI als auch eine Konsole verwendet (z.B. muss man beim Schließen der Konsole verhindern, daß das (GUI-)Programm auch geschlossen wird - nur eines der Probleme die auftauchen werden)...

Ein uraltes Projekt von mir (welches farbige (RTF-)Screenshots von einem laufenden UPX erstellte) verlief im Sand, da die notwendigen Erweiterungen und Anpassungen an diverse Windows-Versionen kein Ende nahmen.
Kleiner Tipp am Rande: beim Screendump einer Konsole sollte man sich selbigen in Blöcken holen (nicht größer als 4KB), sonst kommt es auf diversen Systemen zu Fehlern.

Ergo, was Du möchstest ist aufwendig und erfordert viele Tests.
Ob es fertige Komponenten dafür gibt weiß ich nicht (möchte ich aber bezweifeln).

/edit: typos
  Mit Zitat antworten Zitat
Jörn

Registriert seit: 5. Sep 2003
Ort: Helmstedt
312 Beiträge
 
#4

Re: Commandline-Tool in Delphi-Prog umleiten

  Alt 20. Jan 2004, 23:26
Hmm ich komme so gesehen auch ohne die Textausgaben aus...
Problem ist, das mein Delphi-Prog meistens einfriert. Ich befürchte das es an dem cmd-tool liegt; wenn ich seinen Prozess abschiesse, läuft mein Prog normal weiter, gibt sogar den Stand der Dinge aus. Zumindest die ersten ~65 Zeilen, immer gleiche Anzahl. Ich glaube das cmd-tool stürzt dann ab, obwohl es pur immer extrem stabil lief.

Das abstürzen scheint von der Dauer abzuhängen, mit welcher das Tool läuft. Bei geringer Bearbeitungszeit, stürzt nichts ab, bei längerer (10 sek aufwärts ?) ist nichts zu machen.
  Mit Zitat antworten Zitat
scp

Registriert seit: 31. Okt 2003
1.120 Beiträge
 
Delphi 7 Personal
 
#5

Re: Commandline-Tool in Delphi-Prog umleiten

  Alt 21. Jan 2004, 01:07
Das liegt wie oben gesagt, an den 4KB max. Puffer. Um die längere Verarbeitung zu ermöglichen und den Buffer zu leeren, würde ich es so machen:

Delphi-Quellcode:
procedure CaptureDosCmd(command:String;OutputMemo:TMemo);

//...

  CurSize : Cardinal;
  procedure GetBuffer;
  begin
      Repeat
        BytesRead := 0;
        ReadFile(ReadPipe,CaptureBuffer[0],CaptureBufferSize,BytesRead,nil);
        CaptureBuffer[BytesRead]:= #0;
        OemToAnsi(CaptureBuffer,CaptureBuffer);
        OutputMemo.Text := OutputMemo.Text+String(CaptureBuffer);
      until (BytesRead < CaptureBufferSize);
  end;
begin

//...

      repeat
        WaitHandle := WaitForSingleObject( ProcessInfo.hProcess,0);

        CurSize := FileSeek(ReadPipe,0,2);
        If (CurSize >= 4096) then // Puffer in Memo ausgeben und damit leeren
          GetBuffer;

        Application.ProcessMessages;
      until (WaitHandle = WAIT_OBJECT_0) or (WaitHandle = WAIT_FAILED) or application.terminated;

      if not application.terminated then
        begin
          CurSize := FileSeek(ReadPipe,0,2);
          If (CurSize > 0 ) then // Falls Rest im Puffer, in Memo ausgeben
            GetBuffer;
        end;
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#6

Re: Commandline-Tool in Delphi-Prog umleiten

  Alt 21. Jan 2004, 07:19
Ich weiss zwar nicht wie es geht, aber die JediVCL oder JCL enthaelt eine Funktion dazu.
Auf jeden Fall benutzt der Installer der JVCL 3 (selbst in Source ausgeliefert) so eine Funktion um den Delphi Commandline Compiler zu bedienen.
  Mit Zitat antworten Zitat
NicoDE
(Gast)

n/a Beiträge
 
#7

Re: Commandline-Tool in Delphi-Prog umleiten

  Alt 21. Jan 2004, 07:43
Zitat von scp:
Das liegt wie oben gesagt, an den 4KB max. Puffer.
Habe mich etwas undeutlich ausgedrückt... die 4KB bezogen sich auf das Dumpen in der prozess-eigenen Konsole mittels ReadConsoleOutput().
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#8

Re: Commandline-Tool in Delphi-Prog umleiten

  Alt 21. Jan 2004, 07:43
Wie wärs wenn du das "WaitforSingleObject" rausnimmst und stattdessen eine schleife machst die solange ausgeführt wird wie der prozess nicht beendet ist?!
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Jörn

Registriert seit: 5. Sep 2003
Ort: Helmstedt
312 Beiträge
 
#9

Re: Commandline-Tool in Delphi-Prog umleiten

  Alt 21. Jan 2004, 11:30
Gut ich werd mich mal dran versuchen... die Vorschläge klingen doch recht gut, insbesondere das mit dem 4KB-Puffer...

[edit=sakura] Doppelpost gelöscht. Mfg, sakura[/edit]
  Mit Zitat antworten Zitat
scp

Registriert seit: 31. Okt 2003
1.120 Beiträge
 
Delphi 7 Personal
 
#10

Re: Commandline-Tool in Delphi-Prog umleiten

  Alt 21. Jan 2004, 11:41
Zitat von NicoDE:
Zitat von scp:
Das liegt wie oben gesagt, an den 4KB max. Puffer.
Habe mich etwas undeutlich ausgedrückt... die 4KB bezogen sich auf das Dumpen in der prozess-eigenen Konsole mittels ReadConsoleOutput().
Kommt aber in etwa aufs gleiche raus. Habe festgestellt, das auch das Einlesen per ReadFile() max. 4KB erlaubt. Habe es mit "cmd /c dir C:\ /s" getestet, das hat erst funktioniert, nachdem ich obige Änderungen vorgenomen hab.
  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 08:27 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