![]() |
CommandLineInterpreter aufrufen und Daten übermitteln
Hallo liebe Delphi Gemeinde,
ich bin etwas am verzweifeln und bin mir sicher das der Fehler vor dem Rechner sitzt :D Ich hatte vor eine Art Batch ersatz für Pascal zu entwerfen wo der User eine Liste an Befehlen einer Methode übergibt die eine CLI startet und die Befehle nach und nach abarbeitet. Soweit so gut, bis hier hin bin ich gekommen aber es funktioniert einfach nicht, ich finde leider nicht den Punkt an dem ich etwas falsch mache und erhoffe mir Hilfe.
Delphi-Quellcode:
Momentan wird eine CLI gestartet aber keiner der Befehle erscheint in der CLI.
function ExecuteBatch(const ABatch: TStringList): Boolean;
procedure LWritePipeOut(OutputPipe: THandle; InString: PChar); var byteswritten: DWORD; AnsiBuf: AnsiString; begin AnsiBuf := String(InString) + #13#10; WriteFile(OutputPipe, AnsiBuf, Length(AnsiBuf), byteswritten, nil); end; var i: Integer; LCLI: AnsiString; LSecurityAttribute : TSecurityAttributes; LProcessInformation: TProcessInformation; LStartUpInfo: TStartUpInfo; NewStdIn, WriteStdIn: THandle; begin LCLI := GetEnvironmentVariable('COMSPEC'); UniqueString(LCLI); LSecurityAttribute.nlength := SizeOf(TSecurityAttributes) ; LSecurityAttribute.binherithandle := True; LSecurityAttribute.lpsecuritydescriptor := nil; CreatePipe(NewStdIn, WriteStdIn, @LSecurityAttribute, 0); FillChar(LStartUpInfo, Sizeof(LStartUpInfo), #0) ; LStartUpInfo.hStdInput := NewStdIn; LStartUpInfo.dwFlags := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW; LStartUpInfo.wShowWindow := SW_Show; LStartUpInfo.cb := SizeOf(LStartUpInfo); LStartUpInfo.lpTitle := PChar('Batch Console'); if CreateProcess(nil, PChar(LCLI), @LSecurityAttribute, @LSecurityAttribute, True, CREATE_NEW_CONSOLE or SYNCHRONIZE, nil, nil, LStartUpInfo, LProcessInformation) then begin for i := 0 to Pred(ABatch.Count) do begin LWritePipeOut(WriteStdIn, PChar(ABatch.Strings[i])); end; CloseHandle(LProcessInformation.hProcess); CloseHandle(LProcessInformation.hThread); Result := True end else Result := False; CloseHandle(NewStdIn); CloseHandle(WriteStdIn); end; |
AW: CommandLineInterpreter aufrufen und Daten übermitteln
Selbst unter der Annahme, dass du hier das Rad neu erfinden willst, könnte ein Spicken in einem existierenden Rad vielleicht hilfreich sein:
![]() |
AW: CommandLineInterpreter aufrufen und Daten übermitteln
Immer ein bisschen gucken und mitdenken wenn man Quelltexte von Stack Overflow kopiert.
So funktioniert das:
Delphi-Quellcode:
function ExecuteBatch(const ABatch: TStringList): Boolean;
procedure LWritePipeOut(OutputPipe: THandle; InString: AnsiString); var byteswritten: DWORD; begin InString := InString + sLineBreak; WriteFile(OutputPipe, InString[1], Length(InString), byteswritten, nil); end; var i: Integer; LCLI: AnsiString; LSecurityAttribute: TSecurityAttributes; LProcessInformation: TProcessInformation; LStartUpInfo: TStartupInfoA; NewStdIn, WriteStdIn: THandle; begin Result := False; LCLI := GetEnvironmentVariable('COMSPEC'); UniqueString(LCLI); LSecurityAttribute.nlength := SizeOf(TSecurityAttributes); LSecurityAttribute.binherithandle := True; LSecurityAttribute.lpsecuritydescriptor := nil; CreatePipe(NewStdIn, WriteStdIn, @LSecurityAttribute, 0); FillChar(LStartUpInfo, Sizeof(LStartUpInfo), #0); LStartUpInfo.hStdInput := NewStdIn; LStartUpInfo.dwFlags := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW; LStartUpInfo.wShowWindow := SW_Show; LStartUpInfo.cb := SizeOf(LStartUpInfo); LStartUpInfo.lpTitle := PAnsiChar('Batch Console'); if CreateProcessA(nil, PAnsiChar(LCLI), @LSecurityAttribute, @LSecurityAttribute, True, CREATE_NEW_CONSOLE or SYNCHRONIZE, nil, nil, LStartUpInfo, LProcessInformation) then begin for i := 0 to Pred(ABatch.Count) do begin LWritePipeOut(WriteStdIn, PChar(ABatch.Strings[i])); end; CloseHandle(LProcessInformation.hProcess); CloseHandle(LProcessInformation.hThread); Result := True end; CloseHandle(NewStdIn); CloseHandle(WriteStdIn); end; procedure TForm1.Button1Click(Sender: TObject); var sl: TStringlist; begin sl := TStringlist.create; sl.Add('ping 127.0.0.1'); sl.Add('ping 8.8.8.8'); if ExecuteBatch(sl) then begin Caption := 'fertig'; end; sl.Free; end; |
AW: CommandLineInterpreter aufrufen und Daten übermitteln
Zitat:
Zitat:
Falls es okay ist würde ich dazu gerne noch eine Frage hier stellen, ist es möglich das hStdInput nach meiner For Schleife wieder an den User zurückzugeben? (Beispiel man sendet "Pause") |
AW: CommandLineInterpreter aufrufen und Daten übermitteln
Verstehe die Frage nicht?!
Was macht denn der User mit dem Handle? |
AW: CommandLineInterpreter aufrufen und Daten übermitteln
Zitat:
Delphi-Quellcode:
Wie kann ich den User die Kontrolle über die Eingabe "zurück-geben" bitte?
procedure TForm1.Button1Click(Sender: TObject);
var sl: TStringlist; begin sl := TStringlist.create; sl.Add('pause'); if ExecuteBatch(sl) then begin Caption := 'fertig'; end; sl.Free; end; //edit Also programmatisch zwischen Pipe und GetStdHandle(STD_INPUT_HANDLE) (vermute ich das ich das meine) wechseln |
AW: CommandLineInterpreter aufrufen und Daten übermitteln
Außerdem ist es modern, wenn man sich mit dem passenden ConHost verbindet, anstatt die CMD.exe (COMSPEC) einzubinden.
Frag mich aber bitte nicht, wie man das macht ... ich hatte mal versucht das in der Hilfe zu finden, bzw. im neuen Windows-Terminal im QuellCode abzugucken, aber da sieht ja keiner durch. ![]() ![]() bzw. im aktuellen Windows 11 ist der nun vorinstalliert. ![]() ![]() ![]() PS: Du könntest auch den Windows-Scripting-Host (WSH) verwenden und dann WBScipt, JavaScript oder PowerShell nutzen, sowie optional auch z.B. Pyhon, PascalScript uvm. was sich nachrüsten lässt. |
AW: CommandLineInterpreter aufrufen und Daten übermitteln
Zitat:
|
AW: CommandLineInterpreter aufrufen und Daten übermitteln
Zitat:
- eine konsole öffnen (das ist denke ich mal klar wie kloßbrühe) - befehle übermitteln als ob man sie selbst in einer konsole getippt hätte (ich mache es halt per stringlist) - die kontrolle über StdIn wieder an die konsole übergeben (das ist das einzige was mir momentan fehlt) |
AW: CommandLineInterpreter aufrufen und Daten übermitteln
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:29 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz