Autor Beitrag
Phil511
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Sa 18.10.08 00:25 
ausblenden volle Höhe Delphi-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:
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: Stringvar Output, Errors: TStringList): Boolean;
var
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
  SecurityAttr: TSecurityAttributes;
  PipeOutputRead: THandle;
  PipeOutputWrite: THandle;
  PipeErrorsRead: THandle;
  PipeErrorsWrite: THandle;
  Succeed: Boolean;
  Buffer: array [0..255of Char;
  NumberOfBytesRead: DWORD;
  Stream: TMemoryStream;
begin
  //Initialisierung ProcessInfo
  FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);

  //Initialisierung SecurityAttr
  FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
  SecurityAttr.nLength := SizeOf(SecurityAttr);
  SecurityAttr.bInheritHandle := true;
  SecurityAttr.lpSecurityDescriptor := nil;

  //Pipes erzeugen
  CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);
  CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);

  //Initialisierung StartupInfo
  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), nilnil, true,
  CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nilnil,
  StartupInfo, ProcessInfo) then begin
    result:=true;
    //Write-Pipes schließen
    CloseHandle(PipeOutputWrite);
    CloseHandle(PipeErrorsWrite);

    //Ausgabe Read-Pipe auslesen
    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);

    //Fehler Read-Pipe auslesen
    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;




ausblenden 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;


ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: 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.
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 554

Windows 7 Ultimate
Visual Studio 2008 Pro, Visual Studion 2010 Ultimate
BeitragVerfasst: Sa 18.10.08 00:44 
Das sollte glaube ich über ein Attribut von StartupInfo gehen.
Phil511 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Sa 18.10.08 00:49 
Ist es evt mittels PostMessage möglich?

mfg
Fabian E.
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 554

Windows 7 Ultimate
Visual Studio 2008 Pro, Visual Studion 2010 Ultimate
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: 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...

ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Sa 18.10.08 02:18 
ausblenden 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
  //W := FindWindow(NIL,kProcess);
  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);   //Simuliert Tastendruck
      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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19341
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: 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.

ausblenden volle Höhe Delphi-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
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 27



BeitragVerfasst: Sa 18.10.08 15:16 
Ok hat isch erledigt muss vorher mit Create die Komponente erzuegen...