![]() |
Commandline-Tool in Delphi-Prog umleiten
Mit folgender Prozedur (nich mal von mir *gg*) leite ich die Ausgabe aus einem cmd-tool in ein memo um:
Delphi-Quellcode:
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
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;
Delphi-Quellcode:
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
repeat
WaitHandle := WaitForSingleObject( ProcessInfo.hProcess,100); Application.ProcessMessages; until (WaitHandle <> WAIT_TIMEOUT) or application.terminated;
Delphi-Quellcode:
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.
CaptureDosCmd(cmd+' /c dir '+par,Memo1);
Ich hoffe ich habe das ausreichend erläutert. Schon mal vielen Dank für eure Hilfe MfG |
Re: Commandline-Tool in Delphi-Prog umleiten
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...
|
Re: Commandline-Tool in Delphi-Prog umleiten
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 |
Re: Commandline-Tool in Delphi-Prog umleiten
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. |
Re: Commandline-Tool in Delphi-Prog umleiten
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; |
Re: Commandline-Tool in Delphi-Prog umleiten
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. |
Re: Commandline-Tool in Delphi-Prog umleiten
Zitat:
|
Re: Commandline-Tool in Delphi-Prog umleiten
Wie wärs wenn du das "WaitforSingleObject" rausnimmst und stattdessen eine schleife machst die solange ausgeführt wird wie der prozess nicht beendet ist?!
|
Re: Commandline-Tool in Delphi-Prog umleiten
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] |
Re: Commandline-Tool in Delphi-Prog umleiten
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:18 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz