![]() |
Doskonsole nutzen und Rückgabewerte einlesen
Hallo zusammen,
die Suchfunktion ist mir bekannt :( und ich habe auch schon einige Beiträge gefunden. Bevorzugt wird von mir die Lösung mit der Funtion GetConsoleOutput, welche hier bekannt sein dürfte.
Delphi-Quellcode:
Habe diese Funktion eingebunden und rufe diese wie folgt auf
function TForm1.GetConsoleOutput(const Command: string; Output,
Errors: TStringList): Boolean; var StartupInfo: TStartupInfo; ProcessInfo: TProcessInformation; SecurityAttr: TSecurityAttributes; PipeOutputRead: THandle; PipeOutputWrite: THandle; PipeErrorsRead: THandle; PipeErrorsWrite: THandle; Succeed: Boolean; Buffer: array [0..255] of Char; NumberOfBytesRead: DWORD; Stream: TMemoryStream; begin //Initialisierung ProcessInfo FillChar(ProcessInfo, SizeOf(TProcessInformation), 0); //Initialisierung SecurityAttr FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0); SecurityAttr.nLength := SizeOf(SecurityAttr); SecurityAttr.bInheritHandle := true; SecurityAttr.lpSecurityDescriptor := nil; //Pipes erzeugen CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0); CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0); //Initialisierung StartupInfo FillChar(StartupInfo, SizeOf(TStartupInfo), 0); StartupInfo.cb:=SizeOf(StartupInfo); StartupInfo.hStdInput := 0; StartupInfo.hStdOutput := PipeOutputWrite; StartupInfo.hStdError := PipeErrorsWrite; StartupInfo.wShowWindow := sw_Hide; StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; if CreateProcess(nil, PChar(command), nil, nil, true, CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then begin result:=true; //Write-Pipes schließen CloseHandle(PipeOutputWrite); CloseHandle(PipeErrorsWrite); //Ausgabe Read-Pipe auslesen Stream := TMemoryStream.Create; try while true do begin succeed := ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil); if not succeed then break; Stream.Write(Buffer, NumberOfBytesRead); end; Stream.Position := 0; Output.LoadFromStream(Stream); finally Stream.Free; end; CloseHandle(PipeOutputRead); //Fehler Read-Pipe auslesen Stream := TMemoryStream.Create; try while true do begin succeed := ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil); if not succeed then break; Stream.Write(Buffer, NumberOfBytesRead); end; Stream.Position := 0; Errors.LoadFromStream(Stream); finally Stream.Free; end; CloseHandle(PipeErrorsRead); WaitForSingleObject(ProcessInfo.hProcess, INFINITE); CloseHandle(ProcessInfo.hProcess); end else begin result:=false; CloseHandle(PipeOutputRead); CloseHandle(PipeOutputWrite); CloseHandle(PipeErrorsRead); CloseHandle(PipeErrorsWrite); end; end;
Delphi-Quellcode:
Meine Fehlermeldung:
procedure TForm1.Button2Click(Sender: TObject);
var output, errors: TStringList; begin output:=TStringList.Create; try errors:=TStringList.Create; if GetConsoleOutput('cmd /c dir c:\', output, errors) then Memo1.Lines.AddStrings(output); finally output.free; errors.free; end; end; Zugriffsverletzung bei Adresse ... in Modul 'kernel32.dll'. Schreiben von Adresse ... Fehler tritt an folgender Stelle auf
Delphi-Quellcode:
Arbeite mit Windows7 und Delphi 2010 Prof
if CreateProcess(nil, PChar(command), nil, nil, true,
CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then begin Habe nur den Quellcode übernommen, ich bin mir nicht sicher ober ich noch etwas einbinden oder die dll wie manch Andere ins Verzeichnis der Exe kopieren. |
AW: Doskonsole nutzen und Rückgabewerte einlesen
Das kann ich unter XE nachvollziehen, unter Delphi 2007 keine Probleme. Es ist zwar nicht doll, aber wenn Du explizit auf Ansi einstellst, dann klappt das auch unter XE. Auf die Schnelle:
Delphi-Quellcode:
Zwar nicht schön, klappt aber.
function GetConsoleOutput(const Command: Ansistring; Output,
Errors: TStringList): Boolean; var StartupInfo: TStartupInfoA; ProcessInfo: TProcessInformation; SecurityAttr: TSecurityAttributes; PipeOutputRead: THandle; PipeOutputWrite: THandle; PipeErrorsRead: THandle; PipeErrorsWrite: THandle; Succeed: Boolean; Buffer: array [0..255] of AnsiChar; NumberOfBytesRead: DWORD; Stream: TMemoryStream; begin //Initialisierung ProcessInfo FillChar(ProcessInfo, SizeOf(TProcessInformation), 0); //Initialisierung SecurityAttr FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0); SecurityAttr.nLength := SizeOf(SecurityAttr); SecurityAttr.bInheritHandle := true; SecurityAttr.lpSecurityDescriptor := nil; //Pipes erzeugen CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0); CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0); //Initialisierung StartupInfo FillChar(StartupInfo, SizeOf(StartupInfo), 0); StartupInfo.cb:=SizeOf(StartupInfo); StartupInfo.hStdInput := 0; StartupInfo.hStdOutput := PipeOutputWrite; StartupInfo.hStdError := PipeErrorsWrite; StartupInfo.wShowWindow := sw_Hide; StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; if CreateProcessA(nil, PAnsiChar(command), nil, nil, true, CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then begin result:=true; //Write-Pipes schließen CloseHandle(PipeOutputWrite); CloseHandle(PipeErrorsWrite); //Ausgabe Read-Pipe auslesen Stream := TMemoryStream.Create; try while true do begin succeed := ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil); if not succeed then break; Stream.Write(Buffer, NumberOfBytesRead); end; Stream.Position := 0; Output.LoadFromStream(Stream); finally Stream.Free; end; CloseHandle(PipeOutputRead); //Fehler Read-Pipe auslesen Stream := TMemoryStream.Create; try while true do begin succeed := ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil); if not succeed then break; Stream.Write(Buffer, NumberOfBytesRead); end; Stream.Position := 0; Errors.LoadFromStream(Stream); finally Stream.Free; end; CloseHandle(PipeErrorsRead); WaitForSingleObject(ProcessInfo.hProcess, INFINITE); CloseHandle(ProcessInfo.hProcess); end else begin result:=false; CloseHandle(PipeOutputRead); CloseHandle(PipeOutputWrite); CloseHandle(PipeErrorsRead); CloseHandle(PipeErrorsWrite); end; end; |
AW: Doskonsole nutzen und Rückgabewerte einlesen
MSDN sagt dazu:
Zitat:
|
AW: Doskonsole nutzen und Rückgabewerte einlesen
Dann scheint das MSDN wohl Recht zu haben :lol:
|
AW: Doskonsole nutzen und Rückgabewerte einlesen
Sehr einfach zu fixen:
Delphi-Quellcode:
Dadurch wird der String neu erzeugt und ist beschreibbar.
if CreateProcess(nil, PChar(command + ''), nil, nil, true,
... |
AW: Doskonsole nutzen und Rückgabewerte einlesen
Ein simples Weglassen des
Delphi-Quellcode:
vor Command tuts aber auch.
const
|
AW: Doskonsole nutzen und Rückgabewerte einlesen
Hätte ich auch vermutet, stimmt aber leider nicht.
|
AW: Doskonsole nutzen und Rückgabewerte einlesen
Zitat:
Aber ein
Delphi-Quellcode:
müsste doch gehen?
UniqueString(Command)
|
AW: Doskonsole nutzen und Rückgabewerte einlesen
Japp, so geht' s. Ich habe die Funktion mal schnell umgeschrieben(TStringlist -> TStrings, UniqueString, etc.), Fehler vorbehalten.
Delphi-Quellcode:
Damit kann der Aufruf vereinfacht werden:
function GetConsoleOutput(Command: string; Output, Errors: TStrings): Boolean;
var StartupInfo: TStartupInfo; ProcessInfo: TProcessInformation; SecurityAttr: TSecurityAttributes; PipeOutputRead: THandle; PipeOutputWrite: THandle; PipeErrorsRead: THandle; PipeErrorsWrite: THandle; Succeed: Boolean; Buffer: array [0 .. 255] of Char; NumberOfBytesRead: DWORD; Stream: TMemoryStream; begin // Initialisierung ProcessInfo FillChar(ProcessInfo, SizeOf(TProcessInformation), 0); // Initialisierung SecurityAttr FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0); SecurityAttr.nLength := SizeOf(SecurityAttr); SecurityAttr.bInheritHandle := true; SecurityAttr.lpSecurityDescriptor := nil; // Pipes erzeugen CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0); CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0); // Initialisierung StartupInfo FillChar(StartupInfo, SizeOf(TStartupInfo), 0); StartupInfo.cb := SizeOf(StartupInfo); StartupInfo.hStdInput := 0; StartupInfo.hStdOutput := PipeOutputWrite; StartupInfo.hStdError := PipeErrorsWrite; StartupInfo.wShowWindow := sw_Hide; StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; UniqueString(Command); if CreateProcess(nil, PChar(Command), nil, nil, true, CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then begin result := true; // Write-Pipes schließen CloseHandle(PipeOutputWrite); CloseHandle(PipeErrorsWrite); if Assigned(Output) then begin // Ausgabe Read-Pipe auslesen Stream := TMemoryStream.Create; try while true do begin Succeed := ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil); if not Succeed then break; Stream.Write(Buffer, NumberOfBytesRead); end; Stream.Position := 0; Output.LoadFromStream(Stream); finally Stream.Free; end; end; CloseHandle(PipeOutputRead); if Assigned(Errors) then begin // Fehler Read-Pipe auslesen Stream := TMemoryStream.Create; try while true do begin Succeed := ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil); if not Succeed then break; Stream.Write(Buffer, NumberOfBytesRead); end; Stream.Position := 0; Errors.LoadFromStream(Stream); finally Stream.Free; end; end; CloseHandle(PipeErrorsRead); WaitForSingleObject(ProcessInfo.hProcess, INFINITE); CloseHandle(ProcessInfo.hProcess); end else begin result := false; CloseHandle(PipeOutputRead); CloseHandle(PipeOutputWrite); CloseHandle(PipeErrorsRead); CloseHandle(PipeErrorsWrite); end; end;
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin GetConsoleOutput('cmd /c dir c:\', Memo1.Lines, nil); end; |
AW: Doskonsole nutzen und Rückgabewerte einlesen
Zitat:
Habe den Aufruf nun so modifiziert, da es Fehlermeldungen gab durch Verwendung von TStringList und TStrings.
Delphi-Quellcode:
Bin mir jedoch nicht sicher, ob es da noch eine elegantere Lösung gibt, aber es funktioniert.
procedure TForm1.Button2Click(Sender: TObject);
var SLOut, SLErr: TStringList; I: Integer; begin SLOut := TStringList.Create; SLErr := TStringList.Create; if GetConsoleOutput('cmd /c dir c:\', SLOut, SLErr) then begin for I := 0 to SLOut.Count - 1 do begin Memo1.Lines.Add(SLOut.Strings[I]); end; end; end; Vielen Dank für die Unterstützung. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:53 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 by Thomas Breitkreuz