Autor |
Beitrag |
daywalker0086
Beiträge: 243
Delphi 2005 Architect
|
Verfasst: Mo 14.04.14 13:57
Hallo Jungs und Mädels,
nach längerer Abstinenz melde ich mich mit einem Problem zurück:
Mein Programm startet auf Knopfdruck ein Kommandozeilenprogramm. Dies startet und führt auch aus was es soll.
Allerdings:
Das Programm macht während es läuft mehrere Ausgaben, diese werden jedoch erst in meinem MemoFeld angezeigt wenn das Programm geschlossen wurde.
Ich muss aber wenn das Programm durchgelaufen ist einmal Space drücken damit es sich schließt. Das ist natürlich doof wenn man die Ausgabe Space zu drücken nicht sieht.
Hier mal der jetzige Code:
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:
| function TForm1.RunCaptured(const _dirName, _exeName, _cmdLine: string): Boolean; var start: TStartupInfo; procInfo: TProcessInformation; tmpName: string; tmp: Windows.THandle; tmpSec: TSecurityAttributes; res: TStringList; return: Cardinal; begin Result := False; try tmpName := 'Test.tmp'; FillChar(tmpSec, SizeOf(tmpSec), #0); tmpSec.nLength := SizeOf(tmpSec); tmpSec.bInheritHandle := True; tmp := Windows.CreateFile(PChar(tmpName), Generic_Write, File_Share_Write, @tmpSec, Create_Always, File_Attribute_Normal, 0); try FillChar(start, SizeOf(start), #0); start.cb := SizeOf(start); start.hStdOutput := tmp; start.dwFlags := StartF_UseStdHandles or StartF_UseShowWindow; start.wShowWindow := SW_Minimize; if CreateProcess(nil, PChar(_exeName + ' ' + _cmdLine), nil, nil, True, 0, nil, PChar(_dirName), start, procInfo) then begin SetPriorityClass(procInfo.hProcess, Idle_Priority_Class); WaitForSingleObject(procInfo.hProcess, Infinite); GetExitCodeProcess(procInfo.hProcess, return); Result := (return = 0); CloseHandle(procInfo.hThread); CloseHandle(procInfo.hProcess); Windows.CloseHandle(tmp); res := TStringList.Create; try res.LoadFromFile(tmpName); Memo1.Lines.AddStrings(res); finally res.Free; end; Windows.DeleteFile(PChar(tmpName)); end else begin Application.MessageBox(PChar(SysErrorMessage(GetLastError())), 'RunCaptured Error', MB_OK); end; except Windows.CloseHandle(tmp); Windows.DeleteFile(PChar(tmpName)); raise; end; finally end; end; |
Delphi-Quelltext 1: 2: 3: 4:
| procedure TForm1.Button1Click(Sender: TObject); begin RunCaptured('C:\stvp\','C:\stvp\STVP_CmdLine.exe','-Device=STM32F401xE -ProgMode=SWD -FileProg=nucleo.hex'); end; |
Hier noch die gekürzte Ausgabe des Programms:
Quelltext 1: 2: 3: 4: 5:
| >>> Verifying PROGRAM MEMORY (API) WARNING : ==> Reset done, device Running... <<< Verifying PROGRAM MEMORY succeeds
Hit 'Space' key to stop or any other key to Loop |
Vielleicht ist es nur ein Parameter den man umstellen kann?
Wer kann helfen?
Grüße Christian
|
|
jaenicke
Beiträge: 19284
Erhaltene Danke: 1742
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 14.04.14 14:20
Statt die Ausgabe in eine Datei umzuleiten solltest du diese lieber in eine Pipe umleiten. Die kannst du auch direkt auslesen während das Programm noch läuft. Mit GetConsoleOutput solltest du z.B. Ergebnisse finden, das ist eine fertige Funktion dafür, die im Netz herumspukt, auch hier im Forum AFAIK.
|
|
daywalker0086
Beiträge: 243
Delphi 2005 Architect
|
Verfasst: Mo 14.04.14 15:37
Hi und danke für die Antwort,
ich habe inzwischen die Komponente TDosCommand installiert da ich in dem Threat welchen du auch beantwortet hast gesehen habe das dort die Ausgabe direkt kommen soll:
www.entwickler-ecke....doscommand+onnewline
Leider kommt bei mir das auch erst am Ende, bzw. was noch problematischer ist: wenn das Programm einen Fehler hat, dann beendet sich der Prozess von selbst und die komplette Ausgabe wird danach in meinem Memofeld angezeigt. Wenn das Programm aber durchläuft fordert es einen zum schluss auf die Space Taste zu drücken um es zu beenden.
Da ich aber nichts sehe kann ich auch kein Space drücken...
Hier der kurze Code:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| procedure TForm1.Button3Click(Sender: TObject); var t:string; begin DosCommand1.CommandLine:= 'C:\stvp\STVP_CmdLine.exe -Device=STM32F401xE -ProgMode=SWD -FileProg=nucleo.hex'; DosCommand1.WorkingDirectory:='C:\stvp\';
DosCommand1.OutputLines:= Memo1.Lines;
DosCommand1.Execute; while DosCommand1.Active do Application.ProcessMessages; end;
procedure TForm1.DosCommand1NewLine(Sender: TObject; NewLine: string; OutputType: TOutputType); begin cmd_receivedtext:= NewLine; if cmd_receivedtext <> NewLine then Memo1.Lines.Add(NewLine); end; |
Wie kann ich es besser machen auch in Bezug auf das Drücken der Leertaste, dass das auch automatisiert wird?
|
|
jaenicke
Beiträge: 19284
Erhaltene Danke: 1742
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 14.04.14 16:31
Ich kann gerade nicht schauen, aber ich glaube die Komponente hatte auch Write oder so etwas um etwas an das Programm zu schicken.
|
|
daywalker0086
Beiträge: 243
Delphi 2005 Architect
|
Verfasst: Mo 14.04.14 16:44
Ja ich habe DosCommand1.SendLine('test',TRUE); gefunden.
Wenn ich das so aufrufe:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| procedure TForm1.Button3Click(Sender: TObject); var t:string; begin DosCommand1.CommandLine:= 'cmd.exe '; DosCommand1.WorkingDirectory:='C:\';
DosCommand1.OutputLines:= Memo1.Lines; DosCommand1.Execute; DosCommand1.SendLine('cd stvp',TRUE); DosCommand1.SendLine('STVP_CmdLine.exe',TRUE); end; |
Dann öffnet er auch das Programm und die ersten Zeilen (was ich mit Sendline schicke) werden auch gleich in das Memofeld geschrieben.
Aber dann dauert es eine Weile in der nichts kommt und dann kommt auf einmal die gesamte Ausgabe des Programms (da ich es ohne Paramter aufgerufen habe und es sich dadurch selbst beendet. Ich wüsste eben so nicht wo ich das Schicken eines Leerzeichen einfügen sollte denn so wie es jetzt aussieht wird:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TForm1.DosCommand1NewLine(Sender: TObject; NewLine: string; OutputType: TOutputType); begin cmd_receivedtext:= NewLine; if cmd_receivedtext <> NewLine then Memo1.Lines.Add(NewLine);
end; |
entgegen der eigentlichen Intention erst aufgerufen wenn der Prozess wieder beendet ist.
Mir fällt da nichtsmehr ein, da die Componente ja auch auf CreateProcess, was ich in anderen Codebeispielen gesehen habe beruht.
|
|
daywalker0086
Beiträge: 243
Delphi 2005 Architect
|
Verfasst: Di 15.04.14 10:39
gib es denn eine Möglichkeit die Ausgaben einer Eingabeaufforderung die mit Shellexecute aufgerufen wurde in men Programm zu kopieren?
Delphi-Quelltext 1:
| failure:=ShellExecute(Handle,'open','c:\stvp\STVP_CmdLine.exe','-Device=STM32F401xE -ProgMode=SWD -FileProg=nucleo.hex','c:\stvp',SW_ShowNormal) ; |
Hintergrund ist der das wnn ich das Programm so aufrufe dort alles angezeigt wird und ich wenn es soweit ist, dazu aufgefordert werde die Taste zu drücken. So würde mir das schon ausreichen.
Ich müsste aber am Schluss nochmal die Ausgaben in meinem Programm haben zu Dokumentationszwecken. Geht das irgendwie?
Mit createprocess und mit der Komponente TDosCommand öffnet sich zwar die Eingabeaufforderung aber sie bleibt leer und ich muss auf verdacht die Leertaste drücken. Wenn dann das Programm fertig ist schließt sich das Fenster und ich habe meine Eingaben im MemoFeld. So ist das aber Sch**ße da jemand anders nicht weis das er die Leertaste zu drücken hat.
|
|
|