Autor |
Beitrag |
lorus
Hält's aus hier
Beiträge: 8
|
Verfasst: 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:
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:
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 matze: Code- durch Delphi-Tags ersetzt
|
|
Andidreas
      
Beiträge: 114
Windows XP Pro
BDS 2006
|
Verfasst: So 03.12.06 00:42
Versuch doch mal ob Du damit besser fährst: www.delphipraxis.net...hlight=runconsoleapp RunConsoleApp
|
|
lorus 
Hält's aus hier
Beiträge: 8
|
Verfasst: 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
      
Beiträge: 114
Windows XP Pro
BDS 2006
|
Verfasst: So 03.12.06 14:31
|
|
Andidreas
      
Beiträge: 114
Windows XP Pro
BDS 2006
|
Verfasst: So 03.12.06 15:42
Lad Dir RunConsoleApp runter, binde es ein und probier folgendes:
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 Christian S.: Code- durch Delphi-Tags ersetzt
|
|
lorus 
Hält's aus hier
Beiträge: 8
|
Verfasst: 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
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: string; const 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), nil, nil, False, 0, nil, nil, 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, 0, 0, 0, 0, 0, SWP_NOSIZE or SWP_SHOWWINDOW); Result:= Console; end; end; |
Den meintest doch oder?
Und dann über den Button:
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 Christian S.: Code- durch Delphi-Tags ersetzt
|
|
Andidreas
      
Beiträge: 114
Windows XP Pro
BDS 2006
|
Verfasst: So 03.12.06 15:57
Versuch es mal hiermit:
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 - 1] of 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; else SA.lpSecurityDescriptor := nil; end; SA.nLength := SizeOf(SECURITY_ATTRIBUTES); SA.bInheritHandle := True; SysUtils.Win32Check(CreatePipe(NewStdIn, WriteStdIn, SA, 0)); if not CreatePipe(ReadStdOut, NewStdOut, SA, 0) then begin CloseHandle(NewStdIn); CloseHandle(WriteStdIn); SysUtils.RaiseLastWin32Error; end; GetStartupInfo(SI); SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW; SI.wShowWindow := SW_HIDE; SI.hStdOutput := NewStdOut; SI.hStdError := NewStdOut; SI.hStdInput := NewStdIn; if not CreateProcess(nil, PChar(CommandLine), nil, nil, True, CREATE_NEW_CONSOLE, nil, nil, SI, PI) then begin CloseHandle(NewStdIn); CloseHandle(NewStdOut); CloseHandle(ReadStdOut); CloseHandle(WriteStdIn); SysUtils.RaiseLastWin32Error; end; Last := ''; BufferSize := MaxBufSize; Buffer := AllocMem(BufferSize); try repeat SysUtils.Win32Check(GetExitCodeProcess(PI.hProcess, ExitCode)); PeekNamedPipe(ReadStdOut, Buffer, BufferSize, @Bread, @Avail, nil); if (Bread <> 0) then begin if (BufferSize < Avail) then begin BufferSize := Avail; ReallocMem(Buffer, BufferSize); end; 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; #13: begin inc(I); if (I < Bread) and (Buffer^[I] = #10) then inc(I); AStrings.Add(Str); Str := ''; end; else begin Str := Str + Buffer^[I]; inc(I); end; end; end; Last := Str; end; Sleep(1); Application.ProcessMessages; until (ExitCode <> STILL_ACTIVE); if Last <> '' then AStrings.Add(Last); finally FreeMem(Buffer); end; CloseHandle(PI.hThread); CloseHandle(PI.hProcess); CloseHandle(NewStdIn); CloseHandle(NewStdOut); CloseHandle(ReadStdOut); CloseHandle(WriteStdIn); end; |
Moderiert von Christian S.: Code- durch Delphi-Tags ersetzt
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: 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 
Hält's aus hier
Beiträge: 8
|
Verfasst: 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
      
Beiträge: 114
Windows XP Pro
BDS 2006
|
Verfasst: So 03.12.06 16:47
@Christian S.: und in was steht der Delphicode derzeit?
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: So 03.12.06 16:52
Andidreas 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
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 03.12.06 19:38
lorus hat folgendes geschrieben: | Folgendes Testprogramm habe ich erstellt:
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.
lorus 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.
lorus 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:
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:
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 
Hält's aus hier
Beiträge: 8
|
Verfasst: 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.
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
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 04.12.06 00:30
lorus 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...
jaenicke 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. |
lorus 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: 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 
Hält's aus hier
Beiträge: 8
|
Verfasst: 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
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
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
Hält's aus hier
Beiträge: 8
|
Verfasst: Mo 04.12.06 13:31
jaenicke 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.
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 
Hält's aus hier
Beiträge: 8
|
Verfasst: 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
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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.
|
|
|