Re: mit der console interaktiv komunizieren
|
Re: mit der console interaktiv komunizieren
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:
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....
{ 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; und diesen code habe ich im delphi-treff gefunden
Delphi-Quellcode:
bei diesem kann ich zwar ein cd.. machen aber wenn ich mir denn verzeichnis inhalt anzeigen lasse, zeigt er nicht das übergeordnete verzeichnis
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; dieser code kommt von supermuckel ein mitglied der DP
Delphi-Quellcode:
wenn ich hier die console mit dem parameter "/K" starte, hängt sich das programm auf. es läuft nur sauber mit dem "/C"
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; |
Re: mit der console interaktiv komunizieren
Zitat:
also scheint es wohl nur abgestürzt zu sein.. ich bin da auch kein experte ! |
Re: mit der console interaktiv komunizieren
Zitat:
MfG Binärbaum |
Re: mit der console interaktiv komunizieren
Zitat:
|
Re: mit der console interaktiv komunizieren
Liste der Anhänge anzeigen (Anzahl: 1)
ich glaube das hier könnte die lösung sein. ich bin nicht mehr sicher wo ich es gestern gefunden habe, ich glaube bei torry... ich häge es einfach mal an.
|
Re: mit der console interaktiv komunizieren
Moin, moin
1. Der Glaube ist wieder im Kommen, aber bei mir kommt bei dem Click auf 'Run' nur ein leidiges 'Error creating Pipe A'. 2. Wie man eine Eingabe abfängt ist nicht gelöst. 3. Soweit war ich vor längerem schon mal und die Lösung liegt in der DP unter DP-Beitrag: Dos-Befehle in Delphi - Teillösoung . Man kann damit Befehle ausfürhen, die nur Anzeigen. Das Eingabeproblem blieb damals auch schon offen. Schönes Wochenende // Martin |
Re: mit der console interaktiv komunizieren
also bei mir funzt es bis jetzt hervorranged. es tretten genau(!!!) die gleichen oder selben fehler auf wie bei "professionellen" löungen die man kaufen kann. zb. wenn ich dort dos ftp nehmen will, geht das nicht so richrig. wenn ich es in einem script ausführe weden mir zwar fehler angezeigt, aber das get bzw put hat funktioniert. ich habe versucht ein ping -t www.google.de zumachen das geht unterbrechen kann ich es zwar nicht mehr, geht aber bei der RCmd View aus den NT-Utilitys auch nicht bei den tools von sysinternals kann ich es zwar mit strg+c abbrechen, aber ich kann die console dann auch nicht weiter benutzen.
|
Re: mit der console interaktiv komunizieren
Moin, moin
Hm, war ein ME-Rechner. Vielleicht liegt es daran. Grüße // Martin |
Re: mit der console interaktiv komunizieren
möglich. ich habe win2kpro drauf und es läuft einwandfrei (bis auf eben die fehler welche in komerzieller software auch sind) hast du "cmd.exe" gegen "command.com" ausgetauscht und den phat angepasst? übrigends: die unit RedirectConsole.pas enthält eine funktion "function IsWinNT" hast du dir das schonmal angesehen?
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:04 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz