Einzelnen Beitrag anzeigen

Benutzerbild von Harry M.
Harry M.

Registriert seit: 29. Okt 2004
Ort: Halle
462 Beiträge
 
#12

Re: mit der console interaktiv komunizieren

  Alt 1. Apr 2005, 13: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"
Harry
Gruß Harry
www.H-Soft.info
  Mit Zitat antworten Zitat