AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi mit der console interaktiv komunizieren
Thema durchsuchen
Ansicht
Themen-Optionen

mit der console interaktiv komunizieren

Offene Frage von "DracoBlue"
Ein Thema von Harry M. · begonnen am 1. Apr 2005 · letzter Beitrag vom 14. Feb 2008
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von Kedariodakon
Kedariodakon

Registriert seit: 10. Sep 2004
Ort: Mönchengladbach
833 Beiträge
 
Delphi 7 Enterprise
 
#11

Re: mit der console interaktiv komunizieren

  Alt 1. Apr 2005, 14:43
*WAr Müll*

Bye

Edit Was anderes: http://wwwcip.informatik.uni-erlange...l/kanaele.html
Christian
  Mit Zitat antworten Zitat
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, 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"
Harry
Gruß Harry
www.H-Soft.info
  Mit Zitat antworten Zitat
supermuckl

Registriert seit: 1. Feb 2003
1.340 Beiträge
 
FreePascal / Lazarus
 
#13

Re: mit der console interaktiv komunizieren

  Alt 1. Apr 2005, 22:06
Zitat:
parameter "/K" starte, hängt sich das programm auf
es wird halt wie in der hilfe angegeben halt nicht beendet sondern wartet es
also scheint es wohl nur abgestürzt zu sein..

ich bin da auch kein experte !
Das echte Leben ist was für Leute...
... die im Internet keine Freunde finden!
  Mit Zitat antworten Zitat
Benutzerbild von Binärbaum
Binärbaum

Registriert seit: 19. Jan 2005
Ort: Elstra
764 Beiträge
 
Delphi 7 Enterprise
 
#14

Re: mit der console interaktiv komunizieren

  Alt 2. Apr 2005, 01:41
Zitat:
parameter "/K" starte, hängt sich das programm auf
Da könnte man doch ein "exit" übergeben, damit die Console beendet wird.

MfG
Binärbaum
There are exactly 10 kinds of people: those who understand binary, and those who don't.
---
"Software reift beim Kunden. Bei Hardware ist es anders: Hardware fault beim Kunden." - Rainer G. Spallek
  Mit Zitat antworten Zitat
Benutzerbild von Harry M.
Harry M.

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

Re: mit der console interaktiv komunizieren

  Alt 2. Apr 2005, 11:20
Zitat von Binärbaum:
Zitat:
parameter "/K" starte, hängt sich das programm auf
Da könnte man doch ein "exit" übergeben, damit die Console beendet wird.

MfG
Binärbaum
dafür steht doch schon der parameter /C und die console soll sich ja nicht beenden sondern auf weitere anweisungen warten.
Harry
Gruß Harry
www.H-Soft.info
  Mit Zitat antworten Zitat
Benutzerbild von Harry M.
Harry M.

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

Re: mit der console interaktiv komunizieren

  Alt 2. Apr 2005, 13:18
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.
Angehängte Dateien
Dateityp: zip redirectconsole_402.zip (4,6 KB, 145x aufgerufen)
Harry
Gruß Harry
www.H-Soft.info
  Mit Zitat antworten Zitat
Benutzerbild von mschaefer
mschaefer

Registriert seit: 4. Feb 2003
Ort: Hannover
2.032 Beiträge
 
Delphi 12 Athens
 
#17

Re: mit der console interaktiv komunizieren

  Alt 2. Apr 2005, 14:26
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
Martin Schaefer
  Mit Zitat antworten Zitat
Benutzerbild von Harry M.
Harry M.

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

Re: mit der console interaktiv komunizieren

  Alt 2. Apr 2005, 14:37
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.
Harry
Gruß Harry
www.H-Soft.info
  Mit Zitat antworten Zitat
Benutzerbild von mschaefer
mschaefer

Registriert seit: 4. Feb 2003
Ort: Hannover
2.032 Beiträge
 
Delphi 12 Athens
 
#19

Re: mit der console interaktiv komunizieren

  Alt 2. Apr 2005, 18:05
Moin, moin

Hm, war ein ME-Rechner. Vielleicht liegt es daran.

Grüße // Martin
Martin Schaefer
  Mit Zitat antworten Zitat
Benutzerbild von Harry M.
Harry M.

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

Re: mit der console interaktiv komunizieren

  Alt 2. Apr 2005, 18:24
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?
Harry
Gruß Harry
www.H-Soft.info
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:31 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