![]() |
AW: .exe zu .exe Kommunikation
Ich greife diesen Thread mal auf, weil mein Anliegen thematisch hier sehr gut rein passt. Folgendes Problem bei mir:
1. Es soll zwei Programme geben. Eine Hostanwendung und eine oder mehrere Instanzen einer Client-Anwendung. Beide von mir geschrieben. 2. Die Hostanwendung ist ein Systemdienst, der unter dem SYSTEM-Konto läuft. 3. Die Hostanwendung startet die Client-Anwendung(en) selbst, Art und Weise wie diese Prozesse erzeugt werden, da bin ich flexibel. 4. Die Client-Anwendung beackert externe Programme, die wiederum NICHT von mir sind und hin und wieder mal zu Instabilität neigen. Raucht so ein Programm unerwartet ab, bleibt meine Client-Anwendung u.U. in einem undefinierten Zustand stehen. Deshalb sollen die Client-Anwendungen eine (konfigurierbare) Lifetime haben. Innerhalb derer müssen sie sich sauber beenden (wird in Datenbank geloggt). Tun sie das nicht, sollen sie zuerst vom Host per IPC eine Anweisung zum Shutdown bekommen (wird seitens Hostanwendung ebenfalls geloggt). Reagieren sie darauf auch nicht, z.B. per Antwort-Message und Shutdown, soll die Hostanwendung den hängenden Client-Prozess hart terminieren. Soweit so einfach. Die Kommunikation zwischen meinen beiden Anwendungen ist eher trivial, eine einfache Event-Signalisierung, die keine komplexen Daten übermitteln muss. Schlimmstenfalls ein paar DWords. Der Kniff an der Sache ist, dass die Client-Instanzen ggf. unter abweichenden Benutzerkonten gestartet werden müssen. Das hat mit den wiederum von den Client-Instanzen genutzten externen Programmen zu tun, die aus Sicherheitsgründen nicht im Systemkonto laufen. Darum scheidet wohl alles aus, das auf Window-Handles basiert. Welche Art IPC würdet ihr empfehlen für dieses Szenario? |
AW: .exe zu .exe Kommunikation
TCP/IP über localhost sollte gehen, da die Ports systemweit einmalig sind.
Server Dienst hat einen fixen Port und Clients melden sich dort an und quatschen munter drauf los. Sherlock |
AW: .exe zu .exe Kommunikation
Nja, am "Einfachten" und oft gemacht sind TCP/IP-Verbindungen. (dafür gibt es massenhaft ProcedureCall-Frameworks, wenn du nichts selberbauen willst)
Named-Pipes gingen auch, kommen vom Protokol auf das Gleiche. Oder ohne Name, wenn du irgendwie anders die Handles übergibst. Memory-Mapped-Files (MMF), aber für's "schicken" von Befehlen nicht so praktisch. Also nur MMF ist schlecht, da man dann Pollen müsste, oder über andere Wege (Messages/Events/...) über neue Daten informiert. WindowsMessages gingen, aber da gibt es leider nur die eine WM_COPYDATA, welche auch Texte/Daten übertragen kann (wobei man bei Texten das auch über WM_SETTEXT an ein/mehrere "EDITS" schicken könnte) und dann muß du alles da rein machen, wenn du verschiedene Messages schicken willst, z.B. über ein Byte/Flag am Anfang der Daten. Und bei den Messages mußt du aufpassen, dass sich die Beiden diese Messages überhaupt schicken dürfen. (kennst z.B. von Anwendung an Admin-Anwendung, wo standardmäßig nicht alles erlaubt ist) Alternativ zu WM_COPYDATA, die Daten in MMF, GlobalMemory oder Files und das Handle in LPARAM/WPARAM. |
AW: .exe zu .exe Kommunikation
Hier ist ein Beispiel, in dem ein Indy TCP Server einem Client eine einfache Nachricht sendet. (Artikel
![]() Der Server-Code muss nur in der DoExecute-Methode angepasst werden und dort z.B. das nächste an den Client zu sendende Datenpaket erstellen. Da die Server-Klasse für jede Connection einen eigenen Thread verwendet, gilt der Code in der DoExecute Methode für die aktuelle Connection. DoExecute wird in einer Schleife ausgeführt bis die Verbindung getrennt wurde oder eine Exception auftritt. Der Client-Code läuft in einem Thread um im Hintergrund auf neue Nachrichten des Servers zu warten. Der ReadLn Aufruf wartet, bis entweder eine Nachricht eintrifft, oder das Timeout erreicht ist, und wird dann wieder ausgeführt.
Delphi-Quellcode:
unit Unit1;
interface uses IdCustomTCPServer, IdTCPClient, IdContext, SysUtils, Classes, Forms, StdCtrls, Controls; type TMyPushClientThread = class(TThread) private TCPClient: TIdTCPClient; FLog: TStrings; public constructor Create(AHost: string; APort: Word; ALog: TStrings); destructor Destroy; override; procedure Execute; override; end; TMyPushServer = class (TIdCustomTCPServer) protected function DoExecute(AContext: TIdContext): Boolean; override; end; TServerPushExampleForm = class(TForm) MemoLog: TMemo; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private ExampleClient: TMyPushClientThread; ExampleServer: TMyPushServer; end; var ServerPushExampleForm: TServerPushExampleForm; implementation uses IdGlobal; {$R *.dfm} procedure TServerPushExampleForm.FormCreate(Sender: TObject); begin ExampleServer := TMyPushServer.Create; ExampleServer.DefaultPort := 8088; ExampleServer.Active := True; ExampleClient := TMyPushClientThread.Create('localhost', 8088, MemoLog.Lines); end; procedure TServerPushExampleForm.FormDestroy(Sender: TObject); begin ExampleServer.Free; ExampleClient.Terminate; ExampleClient.WaitFor; ExampleClient.Free; end; { TMyPushServer } function TMyPushServer.DoExecute(AContext: TIdContext): Boolean; begin Result := inherited; // simulate hard work Sleep(Random(3000)); AContext.Connection.IOHandler.WriteLn( 'Completed at ' + TimeToStr(Now), IndyTextEncoding_UTF8); end; { TMyPushClientThread } constructor TMyPushClientThread.Create(AHost: string; APort: Word; ALog: TStrings); begin inherited Create(False); FLog := ALog; TCPClient := TIdTCPClient.Create; TCPClient.Host := AHost; TCPClient.Port := APort; TCPClient.ReadTimeout := 500; end; destructor TMyPushClientThread.Destroy; begin TCPClient.Free; inherited; end; procedure TMyPushClientThread.Execute; var S: string; begin TCPClient.Connect; while not Terminated do begin S := TCPClient.IOHandler.ReadLn(IndyTextEncoding_UTF8); if not TCPClient.IOHandler.ReadLnTimedout then begin TThread.Queue(nil, procedure begin FLog.Append(S); end); end; end; TCPClient.Disconnect; end; end. |
AW: .exe zu .exe Kommunikation
Mich würde auch mal interessieren, wie du Punkt 3 realisieren willst, wenn die unter einem anderen User laufen sollen. Wie macht man sowas?
|
AW: .exe zu .exe Kommunikation
Zitat:
![]() |
AW: .exe zu .exe Kommunikation
|
AW: .exe zu .exe Kommunikation
Zitat:
![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:06 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz