Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi mit der console interaktiv komunizieren (https://www.delphipraxis.net/43313-mit-der-console-interaktiv-komunizieren.html)

Harry M. 1. Apr 2005 12:38


mit der console interaktiv komunizieren
 
ich habe zwar schon mal dies bezüglich im DF gepostet ( http://www.delphi-forum.de/viewtopic...425&highlight= ) aber da ist bis jetzt nix vernüftiges bei rausgekommen also dachte ich ich versuche es mal hier. vielleicht habe ja die leser in der DP einen brauchbaren lösungsvorschlag weil es mir eben auf den nägeln brennt wie man so schön sagt.

also ich habe folgends problem:
mein programm soll ein doscommand an die console übergeben. soweit ist das ja auch kein problem. code dazu findet man ja genug. nur leider ist das was man findet, ein klein wenig an meinem problem vorbei, weil der command ausgeführt wird und das ergebnis in einem memo ausgegeben wird und die console wird dann wieder geschlossen. und genau da sitzt mein problem. die console soll sich nicht schliessen, sondern auf weitere anweisungen warten, eben interaktiv komunizieren, mit meinem programm. bei dem code welchen man findet ist zum beispiel ein cd oder cd.. nicht möglich genausowenig kann man laufende prozeße unterbrechen. wenn ich jetzt zb. in die richtig console eingebe ping -t www.target.de werden fortlaufend singnal zum host gesendet. dies kann ich im normalfall mit strg+c unterbrechen. bei dem code den man findet geht das aber nicht bestenfalls wird das command ausgefüht und man kann es nicht mehr unterbrechen, schlechtenfalls hängt sich das programm ganz auf. je nach dem welchen code man von dem was man findet verwendet.

ich hoffe mir kann jemand helfen.

Luckie 1. Apr 2005 12:52

Re: mit der console interaktiv komunizieren
 
Kommunizier mit der Konsole über Pipes.

Kedariodakon 1. Apr 2005 13:07

Re: mit der console interaktiv komunizieren
 
Zitat:

Zitat von Luckie
Kommunizier mit der Konsole über Pipes.

Hmm ich denkenicht das Ihm dieses Schlagwort "pipes" jetzt wiklcih weiterhilft... :angel2:

Also ich hatte so ein Problem noch nie, ich weiß aber, das man ein CMD starten kann und auf Pipes umleiten, schau dir mal das hier an, vielleicht hilft das irgendwie:

Zitat:

Zitat von cmd /?
Startet eine neue Instanz des Windows 2000-Befehlsinterpreters.

CMD [/A | /U] [/Q] [/D] [/E:ON | /E:OFF] [/F:ON | /F:OFF] [/V:ON | /V:OFF]
[[/S] [/C | /K] Zeichenfolge]

/C Führt den Befehl in der Zeichenfolge aus und endet dann.
/K Führt den Befehl in der Zeichenfolge aus und endet dann nicht.
/S Bestimmt Behandlung von Zeichenfolgen nach /C oder /K (siehe unten).
/Q Schaltet die Befehlsanzeige aus.
/D Deaktiviert die Ausführung von AutoRun-Befehlen von der Registrierung.
/A Ausgabe interner Befehle in eine Pipe oder Datei im ANSI-Format.
/U Ausgabe interner Befehle in eine Pipe oder Datei im UNICODE-Format.
/T:fg Legt die Hinter-/Vordergrundfarben fest (siehe auch COLOR /?).
/E:ON Aktiviert Befehlserweiterungen (siehe unten).
/E:OFF Deaktiviert Befehlserweiterungen (siehe unten).
/F:ON Aktiviert die Ergänzung von Datei- und Verzeichnisnamen.
/F:OFF Deaktiviert die Ergänzung von Datei- und Verzeichnisnamen.
/V:ON Aktiviert verzögerte Erweiterung von Variablen, ! wird dabei als
Trennzeichen verwendet. Zum Beispiel wird mit /V:ON die Variable
!var! zur Ausführungszeit erweitert. Im Gegensatz dazu wird bei
Verwendung der Syntax var die Variable zum Zeitpunkt der Eingabe
aufgelöst (Diese Werte können z.B. in einer FOR-Schleife
unterschiedlich sein!).
/V:OFF Deaktiviert die verzögerte Erweiterung von Variablen.

Hinweis: Mehrere Befehle, die durch das Befehlstrennzeichen "&&" getrennt
sind, werden als Zeichenfolge akzeptiert, wenn diese von Anführungsstrichen
umgeben sind. Aus Kompatibilitätsgründen hat /X die gleiche Funktion wie
/E:ON, /Y hat die gleiche Funktion wie /E:OFF, und /R hat die gleiche Funktion
wie /C. Alle anderen Optionen werden ignoriert.

Wird /C oder /K angegeben, wird der Rest der Befehlszeile nach der Option als
Befehlszeile verarbeitet, wobei folgende Logik zur Verarbeitung des doppelten
Anführungszeichens (") gilt:

1. Sind alle folgenden Bedingungen erfüllt, wird ein doppeltes
Anführungszeichen auf der Befehlszeile beibehalten:

- keine Option "/S"
- genau zwei doppelte Anführungszeichen
- keines der folgenden Zeichen zwischen den doppelten
Anführungszeichen: &<>()@^|
- es ist mindestens ein Leerzeichen zwischen den doppelten
Anführungszeichen
- die Zeichenfolge zwischen den doppelten Anführungszeichen ist der
Name einer ausführbaren Datei

2. Ist dies nicht der Fall, wird bei einem doppelten Anführungszeichen
als erstem Zeichen sowohl dieses, als auch das letzte doppelte
Anführungszeichen entfernt (und der Rest der Befehlszeile bei-
behalten).

Falls /D in der Befehlszeile NICHT angegeben wurde, sucht CMD.EXE
nach den folgenden Registrierungsvariablen. Sollten
eine oder beide vorhanden sein, werden sie zuerst ausgeführt.

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun

und/oder

HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun

Befehlserweiterungen sind standardmäßig aktiviert. Erweiterungen können unter
Verwendung der Option "/E:OFF" für einen bestimmten Aufruf des
Befehlsprozessors deaktiviert werden. Erweiterungen können auch für alle
Aufrufe des Befehlsprozessors deaktivieren werden, indem einer oder beide der
folgenden Werte in der Registrierung auf 0x1 oder 0x0 gesetzt werden (unter
Verwendung von REGEDT32.EXE):

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\EnableExtensions

und/oder

HKEY_CURRENT_USER\Software\Microsoft\Command Processor\EnableExtensions

Die benutzerspezifischen Einstellungen (HKEY_CURRENT_USER) haben gegenüber den
Einstellungen für den Computer (HKEY_LOCAL_MACHINE) Vorrang.
Befehlszeilenoptionen haben Vorrang gegenüber den Registrierungseinstellungen.

Folgende Befehle wurden durch die Befehlserweiterungen geändert bzw. erweitert:

DEL oder ERASE
COLOR
CD oder CHDIR
MD oder MKDIR
PROMPT
PUSHD
POPD
SET
SETLOCAL
ENDLOCAL
IF
FOR
CALL
SHIFT
GOTO
START (umfasst auch Änderungen an externen Befehlsaufrufen)
ASSOC
FTYPE

Sie erhalten weitere Informationen, indem Sie den Befehlsnamen gefolgt von
"/?" eingeben.

Die verzögerte Umgebungsvariablenerweiterung ist standardmäßig NICHT aktiviert.
Die verzögerte Umgebungsvariablenerweiterung kann unter Verwendung der Option
"/V:ON" oder "/V:OFF" für einen bestimmten Aufruf von CMD.EXE
aktiviert bzw. deaktiviert werden. Die verzögerte Umgebungsvariablenerweiterung
kann auch für alle Aufrufe des Befehlsprozessors deaktiviert werden, indem
einer oder beide der folgenden Werte in der Registrierung auf 0x1 oder 0x0
gesetzt werden (unter Verwendung von REGEDT32.EXE):

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\DelayedExpansion

und/oder

HKEY_CURRENT_USER\Software\Microsoft\Command Processor\DelayedExpansion

Die benutzerspezifischen Einstellungen (HKEY_CURRENT_USER) haben gegenüber den
Einstellungen für den Computer (HKEY_LOCAL_MACHINE) Vorrang.
Befehlszeilenoptionen haben Vorrang gegenüber den Registrierungseinstellungen.

Bei aktivierter verzögerter Umgebungsvariablenerweiterung kann das
Ausrufezeichen dazu verwendet werden, den Wert einer Umgebungsvariable zur
Laufzeit zu ersetzen.

Die Namenergänzung für Dateien und Verzeichnisse ist standardmäßig NICHT
aktiviert. Sie kann unter Verwendung der Option "/F:ON" oder "/F:OFF" für einen
bestimmten Aufruf von CMD.EXE aktiviert bzw. deaktiviert werden. Die
Namenergänzung kann auch für alle Aufrufe von CMD.EXE aktiviert werden,
indem einer der folgenden Werte in der Registrierung auf den hexadezimalen Wert
eines Steuerzeichens (z.B. "0x4" für STRG+D und "0x6" für STRG+F) für eine der
beiden Funktionen gesetzt wird:

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\CompletionChar
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\PathCompletionChar

und/oder

HKEY_CURRENT_USER\Software\Microsoft\Command Processor\CompletionChar
HKEY_CURRENT_USER\Software\Microsoft\Command Processor\PathCompletionChar

Die benutzerspezifischen Einstellungen (HKEY_CURRENT_USER) haben gegenüber den
Einstellungen für den Computer (HKEY_LOCAL_MACHINE) Vorrang.
Befehlszeilenoptionen haben Vorrang gegenüber den Registrierungseinstellungen.

Wird die Namenergänzung mit der Option "/F:ON" aktiviert, werden die beiden
Steuerzeichen STRG+D für die Verzeichnisnamenergänzung und STRG+F für die
Dateinamenergänzung verwendet. Um eine der beiden Namenergänzungsfunktionen
in der Registrierung zu deaktivieren, verwenden Sie den Wert für ein
Leerzeichen (0x20), welches kein zulässiges Steuerzeichen darstellt.

Die Namenergänzung wird durch Eingabe eines der beiden Steuerzeichen
ausgeführt. Sie fügt an die Pfadangabe links des Cursors einen Platzhalter an,
wenn dieser nicht bereits vorhanden ist, und erzeugt eine Liste der Pfade, die
übereinstimmen. Anschließend wird der erste Pfad angezeigt. Wurde keine
Pfadübereinstimmung gefunden, ertönt lediglich ein Signalton. Durch wieder-
holte Eingabe des Steuerzeichens werden nacheinander die verschiedenen
Pfadeinträge der Liste angezeigt. Wird zusätzlich die Umschalttaste gedrückt,
werden diese in umgekehrter Reihenfolge angezeigt. Bearbeiten Sie die Zeile,
wird die Liste verworfen und eine neue erstellt. Dies geschieht auch, wenn Sie
zwischen den beiden Namenergänzungsfunktionen umschalten. Der einzige
Unterschied zwischen den beiden Funktionen ist, dass die Dateinamenergänzung
sowohl Dateien als auch Verzeichnisse, die Verzeichnisergänzung jedoch nur
Verzeichnisse auflistet. Wird die Namenergänzung zusammen mit einem der
Verzeichnisbefehle (CD, MD oder RD) verwendet, wird Verzeichnisergänzung
angenommen.

Die Namenergänzung funktioniert auch mit Namen, die Leerzeichen oder
Sonderzeichen enthalten, wenn der Name in doppelte Anführungszeichen
eingeschlossen wird. Wenn Sie den Cursor in einer Zeile nach links bewegen
und die Namenergänzung an dieser Stelle ausführen, wird der Teil der Zeile,
der sich rechts des Cursors befindet, ignoriert.

Die folgenden Sonderzeichen erfordern Anführungszeichen:
<Leerzeichen>
&()[]{}^=;!'+,`~

Wenn du es hinbekommen hast würd ich gern erfahren, wie du das gemacht hast! :cyclops:

Bye

Harry M. 1. Apr 2005 13:10

Re: mit der console interaktiv komunizieren
 
das es an den "Pipes" liegen könnte, konnte ich mir schon denken nur leider versteh ich nicht viel davon. hast du da nicht ein code beispiel für mich (unfähigen api programmierer)?

das was Kedariodakon geschrieben hat hilft mir nicht wirklich weiter, denke ich weil ich ja nicht die "echte" console benutze sondern alles über meine programm laufen lass in und output

Kedariodakon 1. Apr 2005 13:18

Re: mit der console interaktiv komunizieren
 
Zitat:

Zitat von Harry M.
das was Kedariodakon geschrieben hat hilft mir nicht wirklich weiter, denke ich weil ich ja nicht die "echte" console benutze sondern alles über meine programm laufen lass in und output

Hmm meiner Meinung nach, mußt du eine neue CMD-Instanz öffnen und diese natürlich an deine regestrierten Pipes binden, wie solls sonst gehen? :gruebel:

Bye

Harry M. 1. Apr 2005 13:21

Re: mit der console interaktiv komunizieren
 
Zitat:

Zitat von Kedariodakon
wie solls sonst gehen? :gruebel:

ich habe keine ahnung aber du hast mich auf die idee gebacht mal den parameter /k zu übergeben ich bin grad am testen...

doch mit paramter /k gehts !!! den code stelle ich gleich noch vor wo bei ich dazusagen muß, das die eigendliche funktion aus dem delphi-treff ist...

mschaefer 1. Apr 2005 13:26

Re: mit der console interaktiv komunizieren
 
Hallo

Hm, was ist eine regestrierten Pipe und wie greifst Du daruf zu (Codebeispiel). Wie kann man eigentlich auf eine Eingabaufforderung reagieren. Oder wie bekommt man überhaupt mit, das ein Dos Programm auf eine Eingabe wartet?

// Martin

Harry M. 1. Apr 2005 13:28

Re: mit der console interaktiv komunizieren
 
ich doch noch mal was berichtigen.... es wird nur 1x ein verzeichniswechsel aus geführt wenn ich zweimal cd.. cd.. mache gehts nicht. da ich aber insgesamt 4 code beispiele habe werde ich jetzt mal alle durchtesten...

Zitat:

Zitat von mschaefer
Hallo

Hm, was ist eine regestrierten Pipe und wie greifst Du daruf zu (Codebeispiel). Wie kann man eigentlich auf eine Eingabaufforderung reagieren. Oder wie bekommt man überhaupt mit, das ein Dos Programm auf eine Eingabe wartet?

// Martin

folge mal dem link im ersten posting! da findest du zwei weitere

Kedariodakon 1. Apr 2005 13:31

Re: mit der console interaktiv komunizieren
 
Naja die Konsole hat ja nen Output als pipe, der ja nur ausgegeben wird, war irgendwie sowas wie STDOut und ERROut, da muß es auch ein *In* geben :roll:
Nur brauch man die Pipe von der CMD die man gestartet hat ^^

Einzelne befehle kann man sich ja auch auf pips, bzw. datein ausgeben lassen:

dir c:\gibtsnet.haumichtod 1>>STDOut.txt 2>>ErrOut.txt

Normale Ausgabe in STDOut.txt und ERRor Ausgabe in ErrOut.txt...

Bye


Edit zur not die gedrückten Tasten dem CMD zusenden ^^

Harry M. 1. Apr 2005 13:39

Re: mit der console interaktiv komunizieren
 
also wenn ich eingebe "cd.." und lasse mir dann mit "dir" den verzeichnisinhalt anzeigen zeigt er zwar an da er das verzeichnis gewechselt hat aber dir liefert immer noch den alte verzeichnis inhalt

Kedariodakon 1. Apr 2005 13:43

Re: mit der console interaktiv komunizieren
 
*WAr Müll* :oops:

Bye

Edit Was anderes: http://wwwcip.informatik.uni-erlange...l/kanaele.html

Harry M. 1. Apr 2005 13:51

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:
    { 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"

supermuckl 1. Apr 2005 21:06

Re: mit der console interaktiv komunizieren
 
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 !

Binärbaum 2. Apr 2005 00:41

Re: mit der console interaktiv komunizieren
 
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

Harry M. 2. Apr 2005 10:20

Re: mit der console interaktiv komunizieren
 
Zitat:

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 M. 2. Apr 2005 12:18

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.

mschaefer 2. Apr 2005 13:26

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

Harry M. 2. Apr 2005 13:37

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.

mschaefer 2. Apr 2005 17:05

Re: mit der console interaktiv komunizieren
 
Moin, moin

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

Grüße // Martin

Harry M. 2. Apr 2005 17:24

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?

mschaefer 2. Apr 2005 19:31

Re: mit der console interaktiv komunizieren
 
Moin, ziemlich Spätmoin

Delphi-Quellcode:
 if IsWinNT then begin
    InitializeSecurityDescriptor(@sd, SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(@sd, true, nil, false);
    sa.lpSecurityDescriptor:=@sd;
  end else sa.lpSecurityDescriptor:=nil;    { <--   das ist es unter Win9.x }
Jo das wars dann doch,
da ist die Erklärung: Geht nur unter NT.x

So long für heute abend...

// Martin

DracoBlue 1. Mai 2006 18:22

Re: mit der console interaktiv komunizieren
 
Zitat:

Zitat von Harry M.
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.

Das hatte ich auch schon mal - tolles beispiel!

Es funktioniert auch bei allen Anwendungen, nur bei einer nicht. Die Anwendung läuft in der Konsole ohne Probleme aber wenn ich sie mit dem Tool starte bekomme ich andauernd(mind 100x in der Sekunde) die Meldung, dass der Befehl von dem Programm nicht erkannt wird. Heißt für mich, dass das Programm irgendwie glaubt es wären Daten eingegeben (wenn auch fehlerhafte) worden - sind es aber nicht.

Hat jemand vielleicht ein ähnliches Problem, oder weiss wie ich das beheben kann?

Jan

Harry M. 1. Mai 2006 18:27

Re: mit der console interaktiv komunizieren
 
Mit einen Debugger, Tasse Kaffee viel Geduld und tiefergreifenden Delphi-Verständniss :lol:

DracoBlue 1. Mai 2006 18:30

Re: mit der console interaktiv komunizieren
 
Zitat:

Zitat von Harry M.
Mit einen Debugger, Tasse Kaffee viel Geduld und tiefergreifenden Delphi-Verständniss :lol:

*lacht*

Es funktioniert nichtmal, wenn ich in deinem tool cmd.exe starte und damit das Programm öffne *grummel* Das ist kein delphi-verständnis mehr ... das ist Windows API :(.

thule 14. Feb 2008 19:26

Re: mit der console interaktiv komunizieren
 
Verstehe ich jetzt richtig das es nicht möglich ist mit einer consolenanwendung hin UND her, mit dynamischer ein- und ausgabe, OHNE auf das beenden des consoleapps gewartet wird, zu kommunizieren ?

gruß.

DracoBlue 14. Feb 2008 19:49

Re: mit der console interaktiv komunizieren
 
Zitat:

Zitat von thule
Verstehe ich jetzt richtig das es nicht möglich ist mit einer consolenanwendung hin UND her, mit dynamischer ein- und ausgabe, OHNE auf das beenden des consoleapps gewartet wird, zu kommunizieren ?

gruß.

Eigentlich schon. Nur bei einigen Anwendungen nicht.

Schöne Grüße,
Jan


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:51 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