Hallo, nun habe ich schon einige Artikel hier im Forum gefunden wie man einen DOS-Bildschirm übernehmen kann. Das Problem bei mir ist aber, dass ich mit einem batch-file mehrere Befehle aufrufe, die wiederum Meldungen zurückgeben. Das ganze scrollt immer nach oben und erstreckt sich sicher über ca. 200 Zeilen. Mir ReadConsoleInfo bekomme ich aber immer nur den letzten Schirm, die Meldungen die bereits nach oben gescrollt sind bekomme ich aber nicht mehr. Kann mir hier vielleicht jemand weiterhelfen. Ich will einfach alles was im DOS-Fenster ausgegeben wird in mein Memo-Feld bringen. Vielen Dank Peter
Announcement
Collapse
No announcement yet.
DOS -Ausgabe in Memo Feld
Collapse
X
-
Hallo,
man könnte versuchen, die Standard-Ausgabe (StdOutput) in eine Datei umzuleiten und am Ende in die TMemo-Instanz zu laden. Im folgenden Beispiel kann ich den Output von NETSTAT.EXE aus dem Konsolenfenster übernehmen:
<pre>
procedure TForm1.ToolButton1Click(Sender: TObject);
var
aSA : TSecurityAttributes;
aSI : TStartupInfo;
aPI : TProcessInformation;
szTemp : array[0..199] of Char;
FName : String;
hLogFile : THandle;
dwExit : DWORD;
begin
FillChar(aSA, SizeOf(aSA), #0);
aSA.nLength := SizeOf(aSA);
aSA.bInheritHandle := True;
// temp. Dateinamen für Output generieren
FillChar(szTemp, SizeOf(szTemp), #0);
GetEnvironmentVariable(PCHar('TEMP'), szTemp, 180);
FName := szTemp + '\netstat.txt';
// Output-Datei öffnen
hLogFile := CreateFile(PCHar(FName), GENERIC_WRITE or GENERIC_READ,
FILE_SHARE_READ or FILE_SHARE_WRITE,
@aSA, CREATE_ALWAYS, 0, 0);
// Standard-Output in Datei umleiten
GetStartupInfo(aSI);
aSI.dwflags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
aSI.wShowWindow := SW_HIDE;
aSI.hStdOutput := hLogFile;
aSI.hStdError := hLogFile;
if CreateProcess(nil,PChar('netstat'), nil, nil, True,
NORMAL_PRIORITY_CLASS,
nil, nil, aSI, aPI) then
begin
repeat
Application.ProcessMessages;
GetExitCodeProcess(aPI.hProcess, dwExit)
until dwExit <> STILL_ACTIVE;
CloseHandle(aPI.hThread);
CloseHandle(aPI.hProcess);
CloseHandle(hLogFile);
end
else
Abort;
Memo1.Lines.LoadFromFile(FName);
DeleteFile(FName);
end;
</pre>
-
Hallo Peter,<br>wesentlich beschleunigen nicht, da die Konsolenanwendung das Tempo des Output bestimmt. Anbei eine Möglichkeit die Ausgabe in eine Stringlist umzuleiten:<br><PRE>
function TForm1.GetConsoleOutput(const Command: ansiString; var 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
aktiv := true;
//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, 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;
</PRE><br>Übergebe einfach den Commandstring und zwei Stringlisten für die Ausgabe und Errors.<br>Michae
Comment
Comment