AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Name der Windoes Konsole zur KOmmunikation auf cmd.exe?
Thema durchsuchen
Ansicht
Themen-Optionen

Name der Windoes Konsole zur KOmmunikation auf cmd.exe?

Ein Thema von viakt133 · begonnen am 18. Feb 2010 · letzter Beitrag vom 19. Feb 2010
Antwort Antwort
viakt133

Registriert seit: 16. Feb 2010
18 Beiträge
 
Lazarus
 
#1

Name der Windoes Konsole zur KOmmunikation auf cmd.exe?

  Alt 18. Feb 2010, 12:47
Hallo,

Ich habe in Dokus gelesen, das unter Linux eine Konsole unter /dev/ttyX ansprechbar ist. Gibt es da ein Äquivalent in Windows, falls ich auf der Kommandozeile die Konsole als Kommunikationsmedium ansprechen will/muss?

Ist das "con"? Wie beim Kommando "copy con <myfile.txt>"

Oder gibt es da für allgemeine Verwendung noch einen anderen Namen?
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#2

Re: Name der Windoes Konsole zur KOmmunikation auf cmd.exe?

  Alt 18. Feb 2010, 12:53
Linux besitzt Standardkonsolen auf die man im Betrieb umschalten kann. Das gibt es bei Windows nicht, daher kann man nicht so einfach mit Konsolen kommunizieren.
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#3

Re: Name der Windoes Konsole zur KOmmunikation auf cmd.exe?

  Alt 18. Feb 2010, 13:22
Willst du die Konsole zu einem/deinem Prozess ansprechen oder Irgendeine eines anderen Programms?

Es gibt ja nicht nur die eine Konsole, also gibt es da auch keine Allgemeine Adresse, um diese anzusprechen.

Aber die Konsole, welche mit einem bestimmten Programm verbunden ist, läßt sich schon rausfinden und ansprechen (am Einfachsten natürlich die Konsole zum eigenem Programm)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
viakt133

Registriert seit: 16. Feb 2010
18 Beiträge
 
Lazarus
 
#4

Re: Name der Windoes Konsole zur KOmmunikation auf cmd.exe?

  Alt 18. Feb 2010, 18:50
Zitat von himitsu:
Willst du die Konsole zu einem/deinem Prozess ansprechen oder Irgendeine eines anderen Programms?

Es gibt ja nicht nur die eine Konsole, also gibt es da auch keine Allgemeine Adresse, um diese anzusprechen.

Aber die Konsole, welche mit einem bestimmten Programm verbunden ist, läßt sich schon rausfinden und ansprechen (am Einfachsten natürlich die Konsole zum eigenem Programm)
Von meinem Prozess aus die eines anderen Prozesses.
  Mit Zitat antworten Zitat
Astat

Registriert seit: 2. Dez 2009
Ort: München
320 Beiträge
 
Lazarus
 
#5

Re: Name der Windoes Konsole zur KOmmunikation auf cmd.exe?

  Alt 18. Feb 2010, 19:19
Hallo viakt133, du suchst dass!

lg. Astat
Angehängte Dateien
Dateityp: rar console_stdin_stdout_cmd_280.rar (190,8 KB, 40x aufgerufen)
Lanthan Astat
06810110811210410503210511511603209711003210010110 9032084097103
03211611111604403209711003210010110903210010510103 2108101116122
11610103209010110510810103206711110010103210511003 2068101108112
10410503210310111509910411410510109810111003211910 5114100046
  Mit Zitat antworten Zitat
viakt133

Registriert seit: 16. Feb 2010
18 Beiträge
 
Lazarus
 
#6

Re: Name der Windoes Konsole zur KOmmunikation auf cmd.exe?

  Alt 19. Feb 2010, 05:09
Zitat von Astat:
Hallo viakt133, du suchst dass!

JEDI-VCL Demo -> TJvCreateProcess --> JvCreateProcess

lag. Astat
Danke! Von der Aufgabenstellung her, ja. Mein Freund wäre da das CreateProcessExample.dpr. Leider hab ich aber Probleme, die Jedis richtig zu installieren und wenn ich nur den Suchpfad angebe, findet der Compiler auch vieles nicht, was in der folgenden Compilermeldung endet:

[Fataler Fehler] Consts.pas(313): Ausgabedatei '..\..\dcu\Consts.dcu' kann nicht erstellt werden

Habe deshalb gegoogelt und dabei die Windows-API Funktion CreateProcess gefunden. Die gibt doch den Handle des laufenden Prozesses zurück. Könnte dieser Handle nicht auch eine Schnittstelle zu jenem Prozess bilden, den ich von meinem Prozess aus ansprechen will?

Werde mal sicherheitshalber auf diesen Thread hier verlinken. Dort habe ich die für das Problem interessante Funktion function GetProcessHandleFromID(ID: DWORD): THandle; gefunden.

Nun suche ich aber eine möglichst einfache Möglichkeit zur Prozesskommunikation ohne "Schnörkel". Nur zum Experimentieren.
  Mit Zitat antworten Zitat
mse1

Registriert seit: 21. Nov 2007
115 Beiträge
 
#7

Re: Name der Windoes Konsole zur KOmmunikation auf cmd.exe?

  Alt 19. Feb 2010, 07:19
Zitat von viakt133:
Könnte dieser Handle nicht auch eine Schnittstelle zu jenem Prozess bilden, den ich von meinem Prozess aus ansprechen will?
Verbinde vor dem CreateProcess()-Aufruf pipes mit STARTUPINFO hStdInput, hStdOutput und ev. hStdError und setze in dwFlags STARTF_USESTDHANDLES. Dies entspricht dann in etwa stdin, stdout und stderr unter Linux.
http://msdn.microsoft.com/en-us/libr...8VS.85%29.aspx
Beispielcode gibt es z.B. in Free Pascal und MSEgui.

Martin
Martin Schreiber
  Mit Zitat antworten Zitat
Astat

Registriert seit: 2. Dez 2009
Ort: München
320 Beiträge
 
Lazarus
 
#8

Re: Name der Windoes Konsole zur KOmmunikation auf cmd.exe?

  Alt 19. Feb 2010, 10:43
Zitat von viakt133:
..Von der Aufgabenstellung her, ja. Mein Freund wäre da das CreateProcessExample.dpr.
Hallo viakt133, glaub mir, ist nicht Dein Freund, sieh dir mal die Unit uPipedProcess.pas an, und suche nach CreateProcess.

Habe bei meinem vorigen Thread die Attachment, durch nicht Componenten Version ersetzt.

Du kannst es jetzt ohne Komponenten compillieren.

lg. Astat
Lanthan Astat
06810110811210410503210511511603209711003210010110 9032084097103
03211611111604403209711003210010110903210010510103 2108101116122
11610103209010110510810103206711110010103210511003 2068101108112
10410503210310111509910411410510109810111003211910 5114100046
  Mit Zitat antworten Zitat
viakt133

Registriert seit: 16. Feb 2010
18 Beiträge
 
Lazarus
 
#9

Re: Name der Windoes Konsole zur KOmmunikation auf cmd.exe?

  Alt 19. Feb 2010, 12:49
Hallo,

Danke erst mal für Eure Antworten. Daraus habe ich mir jetzt die folgende Lösung gebaut:

Delphi-Quellcode:
unit IPCConsole;

interface

var
  StartupInfo: TStartupInfo;

  ProcessInfo: TProcessInformation;

  SecurityAttr: TSecurityAttributes;

  PipeOutputRead: THandle;

  PipeOutputWrite: THandle;

  PipeErrorsRead: THandle;

  PipeErrorsWrite: THandle;

  ConsoleOutput : TStringList;

  ConsoleErrors : TStringList;



function StartProcessDone(const AProcessStartCommand: String): Boolean;

function SendCommandDone(const Command: String; var Output, Errors: TStringList): Boolean;

implementation

function StartProcessDone(const AProcessStartCommand: String): Boolean;
var
  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;

function SendCommandDone(const Command: String; var Output, Errors: TStringList): Boolean;
var
  Succeed: Boolean;

  Buffer: array [0..255] of Char;

  NumberOfBytesRead: DWORD;

  Stream: TMemoryStream;

begin
    //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;

      ConsoleOutput.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;

      ConsoleErrors.LoadFromStream(Stream);

    finally

      Stream.Free;

    end;

end;

initialization
  ConsoleOutput := TStringList.Create;
  ConsoleErrors := TStringList.Create;

finalization
  ConsoleErrors.Free;
  ConsoleOutput.Free;

end.

program p_console_read_write;

uses
  SysUtils,
  Classes,
  IPCConsole in 'IPCConsole.pas';

var
 Command: String;

procedure GetOutputFrom(var OutList: TStringList);
var cnt,i: Integer;
begin
  if Assigned(OutList) then
  begin
    i := 0;
    cnt := OutList.Count;
    while i<cnt do
    begin
      writeln('#### AUSGABE ####::: ',OutList[i]);
      inc(i);
    end;
    Writeln; Writeln;
  end;
end;

begin
  if StartProcessDone('MyProcess.exe') then
  repeat
    Write('Give a Command: '); Readln(Command);
    if SendCommandDone(Command, ConsoleOutput, ConsoleErrors) then GetOutputFrom(ConsoleOutput);
  until Command = 'q';
end.
Nun wird aber in meiner Funktion immer wieder CreateProcess aufgerufen. Wie erreiche ich nun, das beim 2. bis n-ten Durchlauf immer wieder derselbe Prozess benutzt wird und nicht etwa neue Instanzen gestartet werden.

Im MSDN habe ich nur Named Pipes gefunden. Sollte das denn aber nicht auch mit unnamed Pipes gehen.
Sviel ich bis jetzt davon verstanden habe, kann eine unnamed pipe nur in eriner Richtung (lesen oder schreiben) arbeiten. Hier im Quelltext werden aber schon zwei Pipes erzeugt, eine zum Lesen, eine zum Schreiben, wie ich es am Ende ja auch brauche. Aber wie greife ich nun auf diese Pipes zu?


Während ich die Frage formuliere kommen mir Ideen, wie ich mein Ziel erreichen könnte. Aber dennoch habe ich folgende Fragen:

Im obigen Quelltext werden zuerst, nach dem Füllen der StartupInfo die Pipes erzeugt. Dann wird in die Input-Pipe geschrieben, zB. mein Kommando. Das wird dann per MemoryStream in die Output Stringliste geschrieben.

Aber wenn ich das jetzt starte, bleibt der Konsolenbildschirm schwarz. Warum komme ich nicht in die Repeat until Schleife?

Wenn ich mir eine Routine schreibe, die per Pipe ein Kommando sendesn soll, hängt es am Screiben der Pipe. Werde wohl jetzt erst mal Interfaces weiter betrachten.

Delphi-Quellcode:
function SendCommand(const Command: String): Boolean;
var
  Buffer: array[0..255] of char;
  NumberOfBytesWritten: DWORD;
begin
  if PipesUsed then
  begin
    Writeln('Schreiben des Kommandos -> ',Command);
    move(Command[1], Buffer, Length(Command)); Buffer[Length(Command)]:=#0;
    PipesUsed := WriteFile(PipeOutputWrite, Buffer, 255, NumberOfBytesWritten, nil);
    Result := PipesUsed;
  end
  else Result := PipesUsed;
end;
  Mit Zitat antworten Zitat
Antwort Antwort


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 01:53 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