Registriert seit: 29. Okt 2004
Ort: Halle
462 Beiträge
|
Re: mit der console interaktiv komunizieren
1. Apr 2005, 14:51
ich habe jetzt von den 4 codebeispielen das beste rausgesucht wo ein verzeichniswechsel möglich ist:
(ich glaube der war von den schweitzern)
Delphi-Quellcode:
{ Public-Deklarationen }
function RunCaptured(const _dirName, _exeName, _cmdLine: string): Boolean;
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), 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);
{ 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;
procedure TForm1.Button1Click(Sender: TObject);
begin
RunCaptured('C:\', 'cmd.exe', '/K '+Edit1.Text);
end;
aber auch hier gibt es das problem das wenn ich eingebe cd verzeichnis wechselt er zwar aber wenn ich dann wieder "dir" eingebe zeigt er wieder den inhalt von c:\ an. dies liegt daran das ich als arbeitsverzeichnis "c:\" im Button1Click-Ereigeniss übergebe. kann den code jemand umbauen, weil ich kann es nicht....
und diesen code habe ich im delphi-treff gefunden
Delphi-Quellcode:
function GetConsoleOutput(const Command: String; 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
//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;
procedure TForm1.Button1Click(Sender: TObject);
var
output, errors: TStringList;
begin
output:=TStringList.Create;
try
errors:=TStringList.Create;
if GetConsoleOutput('cmd /K '+Edit1.Text, output, errors) then
Memo1.Lines.AddStrings(output);
finally
output.free;
errors.free;
end;
end;
bei diesem kann ich zwar ein cd.. machen aber wenn ich mir denn verzeichnis inhalt anzeigen lasse, zeigt er nicht das übergeordnete verzeichnis
dieser code kommt von supermuckel ein mitglied der DP
Delphi-Quellcode:
function IsWinNT: boolean;
var
osv : OSVERSIONINFO;
begin
result := false;
try
osv.dwOSVersionInfoSize := sizeof(osv);
GetVersionEx(osv);
result := (osv.dwPlatformId = VER_PLATFORM_WIN32_NT);
except
end;
end;
procedure TForm1.GetConsoleOutput(const Command: String);
var
si: TStartupInfo;
pi: TProcessInformation;
sa: TSecurityAttributes;
sd: TSECURITYDESCRIPTOR;
newstdin,newstdout,read_stdout,write_stdin:Thandle;
Succeed: Boolean;
Buffer: array [0..1024] of Char;
NumberOfBytesRead: DWORD;
BytesAvailable: DWORD;
//Stream: TMemoryStream;
app_spawn: string;
exitcode : cardinal;
begin
//Initialisierung ProcessInfo
FillChar(pi, SizeOf(TProcessInformation), 0);
//Initialisierung SecurityAttr
FillChar(sa, SizeOf(TSecurityAttributes), 0);
if IsWinNT then begin
InitializeSecurityDescriptor(@sd,SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(@sd, true, nil, false);
sa.lpSecurityDescriptor := @sd;
end else begin
sa.lpSecurityDescriptor := nil;
end;
sa.nLength := SizeOf(sa);
sa.bInheritHandle := true;
if (not CreatePipe(newstdin,write_stdin,@sa,0)) then begin
CloseHandle(newstdin);
CloseHandle(write_stdin);
exit; //create stdin pipe
end;
if (not CreatePipe(read_stdout,newstdout,@sa,0)) then begin //create stdout pipe
CloseHandle(read_stdout);
CloseHandle(newstdout);
exit;
end;
GetStartupInfo(si); //set startupinfo for the spawned process
{
The dwFlags member tells CreateProcess how to make the process.
STARTF_USESTDHANDLES validates the hStd* members. STARTF_USESHOWWINDOW
validates the wShowWindow member.
}
si.dwFlags := STARTF_USESTDHANDLES OR STARTF_USESHOWWINDOW;
si.wShowWindow := SW_HIDE;
si.hStdOutput := newstdout;
si.hStdError := newstdout; //set the new handles for the child process
si.hStdInput := newstdin;
app_spawn := 'c:\\window3\\system32\\cmd.exe';
//spawn the child process
// if (not CreateProcess(pchar(app_spawn),nil,nil,nil,TRUE,CREATE_NEW_CONSOLE,nil,nil,si,pi)) then begin
if (not CreateProcess(nil, PChar(command), nil, nil, true,CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil,si,pi)) then begin
CloseHandle(newstdin);
CloseHandle(newstdout);
CloseHandle(read_stdout);
CloseHandle(write_stdin);
end else begin
//fillchar(buffer,sizeof(buffer),0);
// main loop
exitcode := 0;
while true do begin
GetExitCodeProcess(pi.hProcess,exitcode); //while the process is running
if (exitcode <> STILL_ACTIVE) then break;
BytesAvailable := 0;
PeekNamedPipe(read_stdout,pchar(buffer[0]),1023,@NumberOfBytesRead,@BytesAvailable,nil);
//check to see if there is any data to read from stdout
if (NumberOfBytesRead <> 0) then begin
if (BytesAvailable > 1023) then begin
while (NumberOfBytesRead >= 1023) do begin
fillchar(buffer,sizeof(buffer),0);
ReadFile(read_stdout,buffer,1023,NumberOfBytesRead,nil); //read the stdout pipe
memo1.Lines.Add(buffer);
end;
end else begin
fillchar(buffer,sizeof(buffer),0);
ReadFile(read_stdout,buffer,1023,NumberOfBytesRead,nil); //read the stdout pipe
memo1.Lines.Add(buffer);
end;
end;
end; // main loop
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(newstdin); //clean stuff up
CloseHandle(newstdout);
CloseHandle(read_stdout);
CloseHandle(write_stdin);
end; // process created
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
GetConsoleOutput('cmd /C '+edit1.Text);
end;
wenn ich hier die console mit dem parameter "/K" starte, hängt sich das programm auf. es läuft nur sauber mit dem "/C"
|