Autor Beitrag
daywalker0086
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 243


Delphi 2005 Architect
BeitragVerfasst: 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:
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:
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
     { Setze ein Temporäres File }
     { Set a temporary file }
     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;
       { Starte das Programm }
       { Start the program }
       if CreateProcess(nil, PChar(_exeName + ' ' + _cmdLine), nilnil, True,
                        0nil, 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);
         { Die Ausgaben hinzufügen }
         { Add the output }
         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;


ausblenden 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:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 14.04.14 14:20 
Statt die Ausgabe in eine Datei umzuleiten :shock: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 243


Delphi 2005 Architect
BeitragVerfasst: 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:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

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


Delphi 2005 Architect
BeitragVerfasst: Mo 14.04.14 16:44 
Ja ich habe DosCommand1.SendLine('test',TRUE); gefunden.
Wenn ich das so aufrufe:
ausblenden 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.OnNewLine:= Memo1.Lines;
//DosCommand1.MaxTimeAfterBeginning:= 20;
 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:
ausblenden 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);
//DosCommand1.SendLine(#32,TRUE);

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


Delphi 2005 Architect
BeitragVerfasst: 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?
ausblenden 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.