| Autor |
Beitrag |
Phil511
      
Beiträge: 27
|
Verfasst: Fr 17.10.08 23:43
Hi,
Ich würde gern während der Laufzeit eine Konsolenanwendung starten. Im Internet habe ich gelesen das das mit Shellexecute oder CreateProcess funktioniert. Außdem hab ich im Internet gelesen das es irgendwie möglich sei die stdout und stdin.
Hab aber jetzt irgendwie keinen Plan wie ich das genau angehen soll.
Hab mir gedacht ich rufe das Programm mittels CreateProcess auf und leite die stdout in ein MemoFeld oder ähnliches um.
Kann mir irgendwer sagen wie ich das am besten mache?
Außerdem würde ich dann noch gern was in die Anwendung übergeben...
Wie könnte ich das am besten machen?
Ich hoff ihr versteht was ich machen will, und das ihr mir helfen könnt.
mfg.Phil
|
|
Boldar
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Sa 18.10.08 00:25
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85:
| function GetConsoleOutput(const Command: String; var Output, Errors: TStringList): Boolean; var StartupInfo: TStartupInfo; ProcessInfo: TProcessInformation; SecurityAttr: TSecurityAttributes; PipeOutputRead: THandle; PipeOutputWrite: THandle; PipeErrorsRead: THandle; PipeErrorsWrite: THandle; Succeed: Boolean; Buffer: array [0..255] of Char; NumberOfBytesRead: DWORD; Stream: TMemoryStream; begin FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);
FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0); SecurityAttr.nLength := SizeOf(SecurityAttr); SecurityAttr.bInheritHandle := true; SecurityAttr.lpSecurityDescriptor := nil;
CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0); CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);
FillChar(StartupInfo, SizeOf(TStartupInfo), 0); StartupInfo.cb:=SizeOf(StartupInfo); StartupInfo.hStdInput := 0; StartupInfo.hStdOutput := PipeOutputWrite; StartupInfo.hStdError := PipeErrorsWrite; StartupInfo.wShowWindow := sw_Hide; StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
if CreateProcess(nil, PChar(command), nil, nil, true, CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then begin result:=true; CloseHandle(PipeOutputWrite); CloseHandle(PipeErrorsWrite);
Stream := TMemoryStream.Create; try while true do begin succeed := ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil); if not succeed then break; Stream.Write(Buffer, NumberOfBytesRead); end; Stream.Position := 0; Output.LoadFromStream(Stream); finally Stream.Free; end; CloseHandle(PipeOutputRead);
Stream := TMemoryStream.Create; try while true do begin succeed := ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil); if not succeed then break; Stream.Write(Buffer, NumberOfBytesRead); end; Stream.Position := 0; Errors.LoadFromStream(Stream); finally Stream.Free; end; CloseHandle(PipeErrorsRead);
WaitForSingleObject(ProcessInfo.hProcess, INFINITE); CloseHandle(ProcessInfo.hProcess); end else begin result:=false; CloseHandle(PipeOutputRead); CloseHandle(PipeOutputWrite); CloseHandle(PipeErrorsRead); CloseHandle(PipeErrorsWrite); end; end; |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| type plistbox = ^tlistbox; type pstringlist = ^tstringlist; ... procedure convert (const a: plistbox; const b: pstringlist; par : boolean);inline; begin a^.Clear; if par then a^.Items.Add('Errors:'); a^.Items.AddStrings(b^); end; |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| var stroutput, strerrors: stringlist; ... begin ... stroutput := tstringlist.Create; strerrors := tstringlist.Create; getconsoleoutput (edit8.Text, stroutput, strerrors); convert (addr(listbox_output), addr(stroutput), false); convert (addr(listbox_errors), addr(strerrors), true); strerrors.free; stroutput.free; |
|
|
Phil511 
      
Beiträge: 27
|
Verfasst: Sa 18.10.08 00:43
Also Danke soweit einmal,
Habe es soweit jetzt mal, soweit ich aber denn quelltext verstanden habe, kann ich damit stdout und stderr auf ner Deplhi Form ausgeben.
Wie kann ich jetzt jedoch beispielsweise einen String an die Konsolenanwendung übergeben?
mfg.Phil
|
|
Fabian E.
      
Beiträge: 554
Windows 7 Ultimate
Visual Studio 2008 Pro, Visual Studion 2010 Ultimate
|
Verfasst: Sa 18.10.08 00:44
Das sollte glaube ich über ein Attribut von StartupInfo gehen.
|
|
Phil511 
      
Beiträge: 27
|
Verfasst: Sa 18.10.08 00:46
Mittels Startup info kann ich beim Programm start Parameter übergeben oder?
Ich will sie aber erst nach einer zeit übergeben!
mfg
|
|
Phil511 
      
Beiträge: 27
|
Verfasst: Sa 18.10.08 00:49
Ist es evt mittels PostMessage möglich?
mfg
|
|
Fabian E.
      
Beiträge: 554
Windows 7 Ultimate
Visual Studio 2008 Pro, Visual Studion 2010 Ultimate
|
Verfasst: Sa 18.10.08 01:10
Du willst dem Programm später Parameter geben? Das wären dann aber keine Parameter mehr. Du kannst der anderen Anwendung natürlich mit PostMessage Nachrichten schicken... Du kannst dir auch mal IPC ansehen.
|
|
Phil511 
      
Beiträge: 27
|
Verfasst: Sa 18.10.08 01:14
Ja is klar sind dann keine Parameter mehr...
Also um das Problem verständlicher zu machen!
Ich öffne ein Konsolenprogramm das anfangs eine gewisse Zeit braucht um sich zu laden...
Quelltext 1: 2: 3: 4: 5:
| initializing memory. initializing tables......................................................... loading pruning table (538 MB) from disk................
enter cube (x to exit): |
und erst wenn die Zeile "enter cube (x to exit): " angezeigt wird will ich denn String übergeben.
Würde das mit PostMessage funktionieren, hab mir das mal angschaut aber irgendwie wüsst ich nicht wie ich da tun soll.
mfg.
|
|
Phil511 
      
Beiträge: 27
|
Verfasst: Sa 18.10.08 02:18
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure TForm1.EnterText(AText: String); var i : Integer; z : Char; begin if W <> 0 then begin showmessage ('OK'); for i := 1 to Length(AText) do begin z := AText[i]; PostMessage(W, wm_KeyDown, ord(z),0); PostMessage(W, wm_KeyUp, ord(z),0); end;
end; end; |
Naja, sollte das nicht eig so funktionieren?
Ka, wennsn sehr dummer Fehler ist bitte verzeiht mir bin, is schon spät.
Wollte das aber eig heute noch fertig machen.
mfg
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 18.10.08 10:28
Hiermit solltest du weiterkommen, damit werden Ein- und Ausgaben auch während der Programmlaufzeit verarbeitet.
maxxdelphisite.free.fr/doscmd.htm
|
|
Phil511 
      
Beiträge: 27
|
Verfasst: Sa 18.10.08 14:58
Es will einfach nicht funltionieren:
Er zeigt mir immer eine Zugriffsverletzung an. Cerstehe aber nicht warum er das macht, finde eig keinen Feherl in meinen Quelltext.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DosCommand;
type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private public DC : TDosCommand; end;
var Form1: TForm1; implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); begin DC.CommandLine := 'optiqtm.exe'; DC.Execute; end;
end. |
mfg
|
|
Phil511 
      
Beiträge: 27
|
Verfasst: Sa 18.10.08 15:16
Ok hat isch erledigt muss vorher mit Create die Komponente erzuegen...
|
|
|