Autor Beitrag
lorus
Hält's aus hier
Beiträge: 8



BeitragVerfasst: Sa 02.12.06 18:44 
Huhu zusammen,

also ich hab mal ein bisschen mit der TDosCommand Komponente rumgespielt und auf ein paar Probleme gestoßen.

Folgendes Testprogramm habe ich erstellt:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.DosCommand1NewLine(Sender: TObject; NewLine: String;
  OutputType: TOutputType);
begin
  DosCommand1.OutputLines := Memo1.Lines;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  DosCommand1.CommandLine := 'ping google.de';
  DosCommand1.Execute;
end;


1. Problem
Die Ausgabe auf das Memo erfolgt erst beim zweiten Klick auf den Button. Woran liegt das?


2. Problem
Die Ausgabe auf das Memo sieht so aus
Zitat:
Ping google.de [66.249.93.104] mit 32 Bytes Daten:



Antwort von 66.249.93.104: Bytes=32 Zeit=22ms TTL=244

Antwort von 66.249.93.104: Bytes=32 Zeit=22ms TTL=244

Antwort von 66.249.93.104: Bytes=32 Zeit=22ms TTL=244

Antwort von 66.249.93.104: Bytes=32 Zeit=22ms TTL=244



Ping-Statistik f�r 66.249.93.104:

Pakete: Gesendet = 4, Empfangen = 4, Verloren = 0 (0% Verlust),

Ca. Zeitangaben in Millisek.:

Minimum = 22ms, Maximum = 22ms, Mittelwert = 22ms


Das heißt es ist immer eine leerzeile zwischen jeder ausgegebenen Zeile. Wie könnte man das ändern, das es wie in der Konsole angezeigt wird.
Das bringt uns auch gleich zum

3. Problem
Die Konsole benutzt wohl einen anderen Zeichensatz, als das Memo. Deswegen werden die Sonderzeichen falsch ausgegeben. Hab mich ein bisschen schlau gemacht und bin auf die Funktionen OemToChar und CharToOem gestoßen und hab es mit folgendem versucht:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm1.DosCommand1NewLine(Sender: TObject; NewLine: String
  OutputType: TOutputType); 
begin 
  DosCommand1.OutputLines := OemToChar(Memo1.Lines); 
end;


Allerdings führt das zu einem Fehler (PAnsiChar und TString sind inkompatible Typen)
Wie könnte ich das richtig umsetzen?

Schonmal vielen Dank für jede Hilfe :-)


Grüße,

Lorus

Moderiert von user profile iconmatze: Code- durch Delphi-Tags ersetzt
Andidreas
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 114

Windows XP Pro
BDS 2006
BeitragVerfasst: So 03.12.06 00:42 
Versuch doch mal ob Du damit besser fährst: www.delphipraxis.net...hlight=runconsoleapp RunConsoleApp
lorus Threadstarter
Hält's aus hier
Beiträge: 8



BeitragVerfasst: So 03.12.06 14:13 
Huhu,

danke für die Antwort, aber das hilft mir nicht so richtig weiter.
Ich wollte ja gerne die Consolen-Ausgabe auf ein Memo umleiten, so wie es die TDosCommand ja auch macht. Nur gefällt es mir noch nicht so richtig, wie sie es macht :)

Gibt es niemanden, der sich mit der Kompo ein bisschen auskennt? :)

Grüße,

Lorus
Andidreas
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 114

Windows XP Pro
BDS 2006
BeitragVerfasst: So 03.12.06 14:31 
Was meinst Du macht RunConsoleApp? So sieht es z.B. aus:
ausblenden Delphi-Quelltext
1:
  RunConsoleApp(Pfad + '\upx.exe ' + Para, Memo1.Lines);					


Moderiert von user profile iconChristian S.: Code- durch Delphi-Tags ersetzt
Andidreas
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 114

Windows XP Pro
BDS 2006
BeitragVerfasst: So 03.12.06 15:42 
Lad Dir RunConsoleApp runter, binde es ein und probier folgendes:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
  Liste: TStringList;
begin
  Liste := TStringList.Create;
  RunConsoleApp('ping google.de', Liste);
  I := Liste.Count - 1;
  while I > -1 do
  begin
    if Pos('Antwort', Liste.Strings[I]) > 0 then
      Liste.Delete(I + 1);
    Dec(I);
  end;
  for I := 0 to Liste.Count - 1 do
  begin
    OemToCharBuff(Pointer(Liste.Strings[I]), Pointer(Liste.Strings[I]), Length(Liste.Strings[I]));;
    Memo1.Lines.Add(Liste.Strings[I]);
  end;
  FreeAndNil(Liste);
  Memo1.Lines.SaveToFile('Ping.txt');
end;

Es dauert zwar etwas länger mit der Anzeige, sieht aber so aus wie Du es willst.

Moderiert von user profile iconChristian S.: Code- durch Delphi-Tags ersetzt
lorus Threadstarter
Hält's aus hier
Beiträge: 8



BeitragVerfasst: So 03.12.06 15:46 
Komme irgendwie nicht so richtig klar,
hab jetzt also ein leeres form mit nem Memo drauf und nem button.

Dann hab ich folgenden Code benutzt

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:
function RunConsoleApp(const FileName: stringconst Parent: THandle): THandle;

  function EnumWindowsProc(hWnd: HWND; lParam: LPARAM): BOOL; stdcall;
  begin
    TList(lParam).Add(Pointer(hWnd));
    Result := True;
  end;

var
  SI: TStartupInfo;
  PI: TProcessInformation;
  List: TList;
  ProcessId: DWORD;
  Console: THandle;
  I: Integer;
begin
  Result:= 0;
  FillChar(SI, SizeOf(TStartupInfo), 0);
  SI.cb := SizeOf(TStartupInfo);
  SI.dwFlags := STARTF_USESHOWWINDOW;
  SI.wShowWindow := SW_HIDE;
  if CreateProcess(nil, PChar(FileName), nilnil, False, 0nilnil, SI, PI) then
  try
    Console:= 0;
    List:= TList.Create;
    try
      repeat
        List.Clear;
        if EnumWindows(@EnumWindowsProc, Longint(List)) then
        begin
          for I := 0 to List.Count - 1 do
          begin
            GetWindowThreadProcessId(Longint(List.Items[I]), ProcessId);
            if PI.dwProcessId = ProcessId then
            begin
              Console:= Longint(List.Items[I]);
              Break;
            end;
          end;
        end;
      until Console <> 0;
    finally
      List.Free; 
    end;
  finally
    CloseHandle(PI.hProcess);
    CloseHandle(PI.hThread);
  end;
  if Console <> 0 then
  begin
    SetParent(Console, Parent);
    SetWindowPos(Console, 00000, SWP_NOSIZE or SWP_SHOWWINDOW);
    Result:= Console;
  end;
end;


Den meintest doch oder? :)

Und dann über den Button:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.Button1Click(Sender: TObject);
begin
  RunConsoleApp('ping google.de', Memo1.Lines);
end;


Dann bekomme ich folgende Fehler:
Zitat:

[Warnung] Unit1.pas(75): Variable 'Console' ist möglicherweise nicht initialisiert worden
[Fehler] Unit1.pas(86): Inkompatible Typen: 'Cardinal' und 'TStrings'
[Fataler Fehler] Project2.dpr(5): Verwendete Unit 'Unit1.pas' kann nicht compiliert werden


Moderiert von user profile iconChristian S.: Code- durch Delphi-Tags ersetzt
Andidreas
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 114

Windows XP Pro
BDS 2006
BeitragVerfasst: So 03.12.06 15:57 
Versuch es mal hiermit:
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:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
procedure RunConsoleApp(const CommandLine: string; AStrings: TStrings);
type
  TCharBuffer = array[0..MaxInt - 1of Char;
const
  MaxBufSize = 1024;
var
  I: Longword;
  SI: TStartupInfo;
  PI: TProcessInformation;
  SA: PSecurityAttributes;
  SD: PSECURITY_DESCRIPTOR;
  NewStdIn: THandle;
  NewStdOut: THandle;
  ReadStdOut: THandle;
  WriteStdIn: THandle;
  Buffer: ^TCharBuffer;
  BufferSize: Cardinal;
  Last: WideString;
  Str: WideString;
  ExitCode: DWORD;
  Bread: DWORD;
  Avail: DWORD;
begin
  GetMem(SA, SizeOf(TSecurityAttributes));
  case Win32Platform of
    VER_PLATFORM_WIN32_NT:
      begin
        GetMem(SD, SizeOf(SECURITY_DESCRIPTOR));
        SysUtils.Win32Check(InitializeSecurityDescriptor(SD, SECURITY_DESCRIPTOR_REVISION));
        SysUtils.Win32Check(SetSecurityDescriptorDacl(SD, True, nil, False));
        SA.lpSecurityDescriptor := SD;
      end{end VER_PLATFORM_WIN32_NT}
  else
    SA.lpSecurityDescriptor := nil;
  end{end case}
  SA.nLength := SizeOf(SECURITY_ATTRIBUTES);
  SA.bInheritHandle := True;
  SysUtils.Win32Check(CreatePipe(NewStdIn, WriteStdIn, SA, 0));
  if not CreatePipe(ReadStdOut, NewStdOut, SA, 0then
  begin
    CloseHandle(NewStdIn);
    CloseHandle(WriteStdIn);
    SysUtils.RaiseLastWin32Error;
  end{end if}
  GetStartupInfo(SI);
  SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
  SI.wShowWindow := {SW_SHOWNORMAL} SW_HIDE;
  SI.hStdOutput := NewStdOut;
  SI.hStdError := NewStdOut;
  SI.hStdInput := NewStdIn;
  if not CreateProcess(nil, PChar(CommandLine), nilnil, True,
    CREATE_NEW_CONSOLE, nilnil, SI, PI) then
  begin
    CloseHandle(NewStdIn);
    CloseHandle(NewStdOut);
    CloseHandle(ReadStdOut);
    CloseHandle(WriteStdIn);
    SysUtils.RaiseLastWin32Error;
  end{end if}
  Last := '';
  BufferSize := MaxBufSize;
  Buffer := AllocMem(BufferSize);
  try
    repeat
      SysUtils.Win32Check(GetExitCodeProcess(PI.hProcess, ExitCode));
      PeekNamedPipe(ReadStdOut, Buffer, BufferSize, @Bread, @Avail, nil);
      if (Bread <> 0then
      begin
        if (BufferSize < Avail) then
        begin
          BufferSize := Avail;
          ReallocMem(Buffer, BufferSize);
        end{end if}
        FillChar(Buffer^, BufferSize, #0);
        ReadFile(ReadStdOut, Buffer^, BufferSize, Bread, nil);
        Str := Last;
        I := 0;
        while (I < Bread) do
        begin
          case Buffer^[I] of
            #0: inc(I);
            #10:
              begin
                inc(I);
                AStrings.Add(Str);
                Str := '';
              end{end #10}
            #13:
              begin
                inc(I);
                if (I < Bread) and (Buffer^[I] = #10then
                  inc(I);
                AStrings.Add(Str);
                Str := '';
              end{end #13}
          else
            begin
              Str := Str + Buffer^[I];
              inc(I);
            end{end else}
          end{end case}
        end{end while}
        Last := Str;
      end{end if}
      Sleep(1);
      Application.ProcessMessages;
    until (ExitCode <> STILL_ACTIVE);
    if Last <> '' then
      AStrings.Add(Last);
  finally
    FreeMem(Buffer);
  end{end try/finally}
  CloseHandle(PI.hThread);
  CloseHandle(PI.hProcess);
  CloseHandle(NewStdIn);
  CloseHandle(NewStdOut);
  CloseHandle(ReadStdOut);
  CloseHandle(WriteStdIn);
end{end procedure}


Moderiert von user profile iconChristian S.: Code- durch Delphi-Tags ersetzt
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: So 03.12.06 16:12 
Hallo!

Bitte benutzt für Delphi-Code die Delphi-Tags. Danke!

Grüße
Christian

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
lorus Threadstarter
Hält's aus hier
Beiträge: 8



BeitragVerfasst: So 03.12.06 16:14 
Die Zeilen sollen aber Step-by-Step (so wie in der Console auch) 'live' ausgegeben werden :)

Dafür ist die TDosCommand-Kompo ideal, bis auf die anfangs von mir genannten Probs :)

Trotzdem danke für deine Mühe.

Grüße,

Lorus
Andidreas
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 114

Windows XP Pro
BDS 2006
BeitragVerfasst: So 03.12.06 16:47 
@Christian S.: und in was steht der Delphicode derzeit?
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: So 03.12.06 16:52 
user profile iconAndidreas hat folgendes geschrieben:
@Christian S.: und in was steht der Delphicode derzeit?
Wie unter jedem Beitrag steht, habe ich Eure Code- durch Delphi-Tags ersetzt. Und es wäre halt schön, wenn Ihr demnächst direkt die Delphi-Tags benutzt

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 03.12.06 19:38 
user profile iconlorus hat folgendes geschrieben:
Folgendes Testprogramm habe ich erstellt:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.DosCommand1NewLine(Sender: TObject; NewLine: String;
  OutputType: TOutputType);
begin
  DosCommand1.OutputLines := Memo1.Lines;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  DosCommand1.CommandLine := 'ping google.de';
  DosCommand1.Execute;
end;


1. Problem
Die Ausgabe auf das Memo erfolgt erst beim zweiten Klick auf den Button. Woran liegt das?
Daran, dass du erst wenn bereits die Ausgabe angefangen wird (die erste Zeile dir über OnNewLine mitgeteilt wird) das Ziel für die Ausgabe angibst. (Wohin die Ausgabe erfolgen soll, weist du ja OutputLines zu...) Aber das musst du vor dem Execute machen, damit es was bewirkt. Nun ja und beim zweiten ButtonClick ist es dann von der vorherigen Ausgabe her zugewiesen.
Alternativ könntest du auch in DosCommand1NewLine die Zeile, die du in NewLine bekommst, direkt ins Memo einfügen.

user profile iconlorus hat folgendes geschrieben:

2. Problem
Die Ausgabe auf das Memo sieht so aus
Zitat:
Ping google.de [66.249.93.104] mit 32 Bytes Daten:



Antwort von 66.249.93.104: Bytes=32 Zeit=22ms TTL=244

Antwort von 66.249.93.104: Bytes=32 Zeit=22ms TTL=244

Antwort von 66.249.93.104: Bytes=32 Zeit=22ms TTL=244

Antwort von 66.249.93.104: Bytes=32 Zeit=22ms TTL=244



Ping-Statistik f�r 66.249.93.104:

Pakete: Gesendet = 4, Empfangen = 4, Verloren = 0 (0% Verlust),

Ca. Zeitangaben in Millisek.:

Minimum = 22ms, Maximum = 22ms, Mittelwert = 22ms


Das heißt es ist immer eine leerzeile zwischen jeder ausgegebenen Zeile. Wie könnte man das ändern, das es wie in der Konsole angezeigt wird.
Ich habe festgestellt, dass jede zweite Zeile fälschlicherweise ankommt, keine Ahnung warum (habs mir nicht so genau angesehen). Aber du musst jedenfalls einfach in OnNewLine nur jede zweite Zeile akzeptieren, also ins Memo einfügen.

user profile iconlorus hat folgendes geschrieben:

Das bringt uns auch gleich zum

3. Problem
Die Konsole benutzt wohl einen anderen Zeichensatz, als das Memo. Deswegen werden die Sonderzeichen falsch ausgegeben. Hab mich ein bisschen schlau gemacht und bin auf die Funktionen OemToChar und CharToOem gestoßen und hab es mit folgendem versucht:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm1.DosCommand1NewLine(Sender: TObject; NewLine: String
  OutputType: TOutputType); 
begin 
  DosCommand1.OutputLines := OemToChar(Memo1.Lines); 
end;


Allerdings führt das zu einem Fehler (PAnsiChar und TString sind inkompatible Typen)
Wie könnte ich das richtig umsetzen?
Ähh, OemToChar bekommt einen PChar, der umgewandelt werden soll, und einen zweiten wo der umgewandelte PChar rein soll. Memo1.Lines ist aber eine Liste von Strings und nicht nur einer.
Entweder wandelst du das ganze NACH der Ausgabe um oder du fügst die Zeilen selbst in OnNewLine ein.

Aussehen tut das dann so:
ausblenden 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:
var
  Form46: TForm46;
  AcceptLine: Boolean;

implementation

{$R *.dfm}

procedure TForm46.btnStartClick(Sender: TObject);
begin
  AcceptLine := True;
  memOutput.Lines.Clear;
  DosCommand1.CommandLine := edtCommandLine.Text;
  DosCommand1.Execute;
end;

procedure TForm46.DosCommand1NewLine(Sender: TObject; NewLine: string;
  OutputType: TOutputType);
begin
  if AcceptLine then
  begin
    if NewLine <> '' then
      OemToChar(PChar(NewLine), PChar(NewLine));
    memOutput.Lines.Add(NewLine);
  end;
  AcceptLine := not AcceptLine;
end;
lorus Threadstarter
Hält's aus hier
Beiträge: 8



BeitragVerfasst: So 03.12.06 23:53 
Hiho jaenicke,

deine Vorschläge haben meine bisherigen Probleme komplett gelöst :)
Vielen Dank dafür :)

So sieht der Code jetzt aus.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TForm1.Button1Click(Sender: TObject);
begin
  AcceptLine := True;
  Memo1.Lines.Clear;
  DosCommand1.CommandLine := 'ping google.de';
  DosCommand1.Execute;
end;

procedure TForm1.DosCommand1NewLine(Sender: TObject; NewLine: String;
  OutputType: TOutputType);
begin
  if AcceptLine then
  begin
    if NewLine <> '' then
      OemToChar(PChar(NewLine), PChar(NewLine));
      Memo1.Lines.Add(NewLine);
  end;
  AcceptLine := not AcceptLine;
end;


Dein Code filtert übrigens auch schon die Leerzeilen raus :)

Jetzt bin ich allerdings schon auf die nächste Frage gestoßen.
Ich möchte nachdem das Programm (in dem Fall der ping) abgeschlossen ist, das Programm erneuert starten, aber mit anderen Parametern (z.B. jetzt ping yahoo.de)

Er soll also google.de pingen, warten bis das fertig ist und dann yahoo.de pingen. (Das mit dem Ping ist nur zum testen :))

Hab es damit versucht, das ich bei dem ButtonClick Event einfach noch ein
'DosCommand1.SendLine('ping yahoo.de',true);' unten dran gehangen hab.
Aber dann passiert gar nix mehr.

Ich glaube ich verstehe die Kompo irgendwie grundsätzlich falsch.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 04.12.06 00:30 
user profile iconlorus hat folgendes geschrieben:
Dein Code filtert übrigens auch schon die Leerzeilen raus :)

Soll er ja auch, was meinst du wofür AcceptLine ist? Dadurch, dass diese Variable mit AcceptLine := not AcceptLine; abwechselnd True und False ist, wird bei if AcceptLine then nur jede zweite Zeile ins Memo eingefügt... ;-)
user profile iconjaenicke hat folgendes geschrieben:
Ich habe festgestellt, dass jede zweite Zeile fälschlicherweise ankommt, keine Ahnung warum (habs mir nicht so genau angesehen). Aber du musst jedenfalls einfach in OnNewLine nur jede zweite Zeile akzeptieren, also ins Memo einfügen.


user profile iconlorus hat folgendes geschrieben:
Jetzt bin ich allerdings schon auf die nächste Frage gestoßen.
Ich möchte nachdem das Programm (in dem Fall der ping) abgeschlossen ist, das Programm erneuert starten, aber mit anderen Parametern (z.B. jetzt ping yahoo.de)

Er soll also google.de pingen, warten bis das fertig ist und dann yahoo.de pingen. (Das mit dem Ping ist nur zum testen :))

Hab es damit versucht, das ich bei dem ButtonClick Event einfach noch ein
'DosCommand1.SendLine('ping yahoo.de',true);' unten dran gehangen hab.
Aber dann passiert gar nix mehr.

Ich glaube ich verstehe die Kompo irgendwie grundsätzlich falsch.

Naja, das ist für dich als Anfänger auch nicht so einfach zu verstehen, was da wirklich passiert. Das mit AcceptLine hätte ich eigentlich erwartet, dass du das verstehst. Was hier aber passiert, ist nicht ganz so einfach.
Weißt du was Threads sind? Das ist ein Prozess, der mehr oder weniger unabhängig von deinem Hauptprozess läuft. Das heißt, wenn du DosCommand1.Execute aufrufst, wird ein neuer Prozess gestartet. Befehle, die nach deinem Befehl im Programm stehen, werden sofort ausgeführt. Der Ping läuft im Hintergrund weiter.

Du musst also warten, bis der Ping fertig ist:
ausblenden Delphi-Quelltext
1:
2:
  while DosCommand1.Active do
    Application.ProcessMessages;

Danach kannst du an CommandLine einfach einen anderen Befehl zuweisen und erneut Execute benutzen.

Was SendLine macht ist folgendes:
Du kennst vielleicht DOS-Befehle, die eine Bestätigung verlangen. Zum Beispiel format für die Formatierung der Festplatte. An dieser Stelle würde dein Programm hier anhalten. Und da könntest du mit SendLine einfach ein j für Ja schicken, damit das DOS-Programm weitermacht.
lorus Threadstarter
Hält's aus hier
Beiträge: 8



BeitragVerfasst: Mo 04.12.06 03:41 
Huhu jaenicke,

du hast recht. das mit dem AcceptLine := not AcceptLine hab ich nicht sofort durchschaut wie es funktioniert. Aber das es dafür verantwortlich hab ich ganz schnell rausgefunden indem ich es mal weggelassen habe. Aber irgendwann wäre ich bestimmt noch drauf gekommen, was genau da passiert :)
Jetzt wo dus sagst, ist es natürlich ganz logisch und simpel ;)
Nur selbst komm ich nicht auf so geniale Ideen :-/

Das mit dem Threads kann ich nach deiner Erklärung nun auch gut nachvollziehen. Er stößt in dem Fall den Ping nur an und macht weiter in seinem eigenen Text. Durch den Zusatz bleibt er aber solange in der Schleife 'gefangen' bis das Programm keine Nachrichten mehr ausgibt.

Sendline hab ich nun auch nochmal ausprobiert. Mit dem von dir angesprochnen format funktioniert es auch wunderbar.
Nun hab ich aber mal weiterprobiert und diskpart hergenommen.
Wenn man das in der Console aufruft startet es und wartet dann auch auf weitere Eingaben. z.B. select disk 0

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TForm1.Button1Click(Sender: TObject);
begin
  AcceptLine := True;
  Memo1.Lines.Clear;
  DosCommand1.CommandLine := 'diskpart';
  DosCommand1.Execute;
  DosCommand1.Sendline('select disk 0', True);
end;


Hier scheint das Sendline aber schon ein Stückchen zu früh zu kommen. Wenn man in der Console schaut braucht es auch immer einen ganz kleinen Moment bis es zur Eingabe bereit ist.
Es gibt bestimmt auch noch andere Consolen Programme die erst ein bisschen rumröteln und dann eine Eingabe wollen. Da kommt das Sendline wohl aber zu früh richtig?
Mit der while Schleife von eben geht es aber auch nicht, da das parallel laufenden Programm ja immernoch am laufen ist.
Kann man da auch irgendwie eingreifen und warten bis das prog die eingabe will oder ließe sich da nur etwas mit einem timer machen?


Grüße,

Lorus
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 04.12.06 08:08 
Also das sollte eigentlich funktionieren, indem die Eingaben mit SendLine direkt nach dem Execute gemacht werden. Der Grund: Das Ganze funktioniert über sogenannte Pipes, also Pipelines. Ausgaben kommen über eine an und Eingaben werden darüber geschickt.
Wenn jetzt das DOS-Programm noch keine Eingabe erwartet, wird auch die Pipe, in die du Eingabedaten schreibst, nicht verarbeitet. Sobald dann eine Eingabe erwartet wird, wartet das DOS-Programmm auf Eingaben von der Eingabepipeline. Im Fall der Verwendung von TDosCommand liest es also eine bestimmte Menge Zeichen (normalerweise bis zu einem gelesenen Enter) aus der Eingabepipeline.

Du kannst also mehrere Eingaben sofort an Execute anschließen und dann mit der while-Schleife auf Beendigung warten. Das sollte funktionieren.
lorus Threadstarter
Hält's aus hier
Beiträge: 8



BeitragVerfasst: Mo 04.12.06 13:31 
user profile iconjaenicke hat folgendes geschrieben:
Im Fall der Verwendung von TDosCommand liest es also eine bestimmte Menge Zeichen (normalerweise bis zu einem gelesenen Enter) aus der Eingabepipeline.


Ah ok dann hat wahrscheinlich nur das Enter gefehlt. Hab im TDosCommand-Code gelesen das DosCommand1.Sendline('', True) wie ein Enter ist.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TForm1.Button1Click(Sender: TObject);
begin
  AcceptLine := True;
  Memo1.Lines.Clear;
  DosCommand1.CommandLine := 'diskpart';
  DosCommand1.Execute;
  DosCommand1.Sendline('select disk 0', True);
  DosCommand1.SendLine('', True);
end;


funktioniert dann also :)

Was könnte man anstatt des '' senden. Mit dem Ascii-Code von der Enter-Taste müsste es dann doch theoretisch auch gehen oder?

Nochmal vielen Dank für deine Hilfe, hast mir echt sehr weitergeholfen und nun passt es auch alles, wie ich es mir vorstellt habe :)

Grüße,

Lorus
lorus Threadstarter
Hält's aus hier
Beiträge: 8



BeitragVerfasst: Mo 04.12.06 13:40 
Hehe war doch ganz anders, bei Diskpart stimmt die Ausgabe .. also keine Leerzeilen dazwischen. Deswegen wurde die eine Zeile auch nicht ausgegeben ;)

Und ich hab mich gewundert warum es abwechseln funktioniert und nicht funktioniert wenn ich auf den button drücke ^^

Grüße,

Lorus
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 04.12.06 16:53 
Wenn die Leerzeichen nicht bei allen Programmen kommen, dann koenntest du sowas machen wie: Die Zeile NICHT akzeptieren, wenn AcceptLine True ist UND die Zeile leer ist. Ob dann AcceptLine auch umgekehrt werden muss, muesstest du halt sehen.
Aber eventuell kannst du das so vielleicht allgemeingueltig hinbekommen.

Eine Moeglichkeit eventuell: Am Anfang ist, wenn alles korrekt ist, EINE Leerzeile. Wenn da mehr als eine ist, dann muss jede zweite nicht akzeptiert werden. Das hab ich jetzt nicht ausprobiert, koennte aber hinkommen ;-)
Wird aber eventuell etwas komplizierter.

Dass es Programme gibt, wo es so ist und andere wo es anders ist, duerfte daran liegen, dass diskpart interaktiv funktioniert... Und dir und sowas einfach nur ausgibt. Ich wuesste zwar jetzt nicht warum, aber das koennte ich mir vorstellen.