![]() |
.exe zu .exe Kommunikation
Hallo Gemeinde!
Ich würde gerne folgendes bewerkstelligen: Man hat 2 .exe Dateien, ich habe eine Funktion oder Procedure in .exe A die einen String an .exe B sendet. Ich habe gerade keine Idee und auch keinen Ansatz wie ich das machen könnte. Ziel soll so etwas sein, stark vereinfacht: Programm A
Delphi-Quellcode:
Programm B = sucht aktiv nach Programm A Prozess und wartet auf eine ID und einen String um den dann Darzustellen.
Procedure SendeAnB(const ID: Byte; const Nachricht: String);
Begin // hier irgendwie die PID von B finden // hier irgendwie die ID und den String an B schicken End; Procedure X; Begin SendeAnB(1, 'Nachricht'); End; Mein momentaner Gedankengang wäre das ich in beiden .exe eine PID abfrage für das andere Kompilat beziehe um bei A ein Senden zu ermöglichen und B sollte halt Empfangen können. Geht so etwas überhaupt mit Delphi und falls es gehen sollte hätte da jemand eine Anlaufstelle für Informationen das ich so etwas hinbekomme? Falls sich jemand fragt was das soll, hier ein Beispiel:
Delphi-Quellcode:
Programm A
SendeAnB(1, 'Starte Berechnung'); Berechne; SendeAnB(2, 'Berechnung beendet'); Programm B case GetMsg.ID of 1: Label1.Caption := GetMsg.Nachricht;; 2: Label2.Caption := GetMsg.Nachricht; end; |
AW: .exe zu .exe Kommunikation
Da bieten sich vielleicht Pipes an:
![]() |
AW: .exe zu .exe Kommunikation
|
AW: .exe zu .exe Kommunikation
Oder Memory Mapped Files (MMF)
![]() ![]() PipeMessages ![]() |
AW: .exe zu .exe Kommunikation
Vielen Dank an alle,
Pipes kannt ich bislang nur um Console Nachrichten abzufangen, das Beispiel im letzten Post bietet sogar eine (fast fertige) Klasse an falls es jemand interessiert! Das hat mir enorm geholfen mich meinem Projekt zu widmen! Ich Untersuche all eure Links und mache das beste daraus, das mit MMF sieht auch cool aus. Vielen Dank!!! edit Der Tipp mit der Seite von m-puff, da bin ich auf etwas noch besseres gestossen: ![]() Wenn ich das zum laufen bekomme erziehlt es genau was ich wollte, kurz klein und schnittig ;-) |
AW: .exe zu .exe Kommunikation
WM_CopyData verwende ich ausschließlich. Es ist unkompliziert und funktioniert problemlos.
Bei mir haben zusammenhängende Exe-Dateien eine ID. Der Sender schickt seine ID im dwData mit und der Empfänger wertet die dann aus. Auf diese einfache Art und Weise werden erstmal nur die eigenen Nachrichten verarbeitet. |
AW: .exe zu .exe Kommunikation
@günni0: Sollte dann die Empfänger .exe sowas wie einen Timer haben oder reicht da eine
Delphi-Quellcode:
im { Public declarations } aus und es sucht automatisch nach Nachrichten?
procedure WMCOPYDATA(var msg: TWMCopyData); message WM_COPYDATA;
Ich habe es bis jetzt noch nicht getestet. |
AW: .exe zu .exe Kommunikation
Die von dir geschriebene Art und Weise ohne Timer reicht.
Mit Timer da ist mir nix gekannt. |
AW: .exe zu .exe Kommunikation
Hey supi, dann mache ich mich mal sofort ans Werk.
Danke für Info! |
AW: .exe zu .exe Kommunikation
Ist wirklich sehr einfach. Pipes und sowas ist viel zu viel Code.
Ob man mit WMCOPYDATA aber eigene Records schicken kann, weiß ich leider nicht. Mir reicht aktuell noch das TCopyDataStruct. |
AW: .exe zu .exe Kommunikation
Schau Dir mal den m-puff @ WMCOPYDATA Link an, da wird es mit einem Record beschrieben was ich genau so übernehmen mag.
Ich ersetze lediglich im Record einen Boolean mit einem Byte. Mein Empfänger soll 3 Zeilen zeigen für 3 verschiedene Nachrichten Typen. 1. Sender fängt eine Operation an 2. Sender hat Operation beendet 3. Auswertungsergebniss von Operation oder Fehlernachricht Ich habe gerade mal gegoogelt und der erste Treffer sagt was über TCopyDataStruct. ![]() |
AW: .exe zu .exe Kommunikation
Ich werfe da mal noch etwas rein. Mag vielleicht im ersten Moment etwas komisch klingen aber du kannst auch
TCP oder UDP für die Kommunikation zwischen Prozessen verwenden. Finde ich z.B. angenehmer zu benutzen als Pipes oder Memory mapped Files. WM_COPYDATA geht auch aber würde ich nicht benutzen wenn die Kommunikation über "Hier nimm das!" hinausgeht. |
AW: .exe zu .exe Kommunikation
@NG: Hättest Du dafür eventuell exemplarisch ein Beispiel-Code oder Link? Ich bin gerade dabei aus allen genannten Varianten eine Beispiel-Demo zu erstellen und anschließend hier zur Verfügung stellen.
|
AW: .exe zu .exe Kommunikation
Ehm.. Ich könnte evtl. später was basteln aber falls du schon mal Netzwerkkram gemacht hast mit TIdTCPClient o.ä. dann müsstest du das auch so hinkriegen.
Es macht letztendlich keinen Unterschied ob die Verbindung zwischen zwei Programmen auf unterschiedlichen PCs besteht oder zwischen 2 Programmen auf dem gleichen PC. Der Code ist derselbe. Falls du mit Sockets noch nie was gemacht hast schau dir mal TIdTCPClient/TIdTCPServer an und such bei Google mal danach. Wirst wahrscheinlich ne Menge finden. Zu Memory mapped Files: Hab damals mal eine Unit dafür gebaut in dem extra eine Klasse für IPC enthalten ist: ![]() Falls du die Jedi JWSCL installiert hast, dann ist diese Unit als "JwsclStreams.pas" schon dabei. |
AW: .exe zu .exe Kommunikation
Danke, der Ansatz genügt mir, damit kann ich was Anfangen. Deine "mappedstreams_151.pas" werde ich mit einbauen ;-)
edit Nein, momentan ist mein Delphi noch relativ jungfräulich was zusatz Pakete betrifft. Ein paar Kauf-Pakete sind drinnen, das war's dann schon. |
AW: .exe zu .exe Kommunikation
WM_COPYDATA kommt spätestens an seine Grenzen, wenn ein Prozess elevated ist und der andere nicht (was logischerweise auch der Fall ist bei Kommunikation mit einem Systemdienst). Auch mit mehreren Prozessen auf verschiedenen Sessions (RDP, Fast User Switching, Terminal Services) kommt man da nicht weiter.
Ob WM_COPYDATA, Pipes, MMF, oder TCP - das kommt sicher auf den Verwendungsfall an. In Prozessen, von denen es nur eine Instanz geben soll, übergebe ich ich Parameter an den bereits laufenden Prozess per Pipe, da fällt WM_COPYDATA auch schon aus, weil der laufende Prozess ja elevated sein kann. MMF verwende ich beispielsweise, um in einem Systemdienst einen Status zu schreiben, auf den mehrere andere Prozesse dann nur lesend zugreifen. Ist einfach zu greifen weil kaum anders als Dateihandling. Mit TCP kann man ziemlich viel, ich würde da aber auf bewährte Kontrollstrukturen zurückgreifen, mindestens https, warum nicht gleich webservices, da muss man mit entsprechenden Helfern keine einzelne Zeile selberschreiben? |
AW: .exe zu .exe Kommunikation
Liste der Anhänge anzeigen (Anzahl: 1)
Ich bin bereits daran alle Möglichkeiten einzubinden, siehe Bild Anhang 48925
edit Erster Test mit WMCOPYDATA ergab übrigens genau was Du sagst, wenn Server Admin ist und Client nicht dann klappt es nicht. |
AW: .exe zu .exe Kommunikation
Wenn dein Beispiel gut funktioniert, sollte man es in die CodeLib aufnehmen wie ich finde.
Dann gäbe es eine zentrale Anlaufstelle für alle Fragesuchenden dieses Themas. |
AW: .exe zu .exe Kommunikation
Da hätte ich Grundsätzlich nichts gegen einzuwänden aber das überlasse ich wichtigeren Menschen ;-)
Momentan tüftel ich daran wie ich jede Methode in eine einzelne Unit quetsche damit man dann nur noch die entsprechende Unit sich rausfischen brauch, falls Bedarf an so etwas besteht. Mein Sorgenkind ist gerade eher der Client, dem bringe ich gerade bei auf die verschiedenen Methoden auch korrekt zu reagieren, auch da wieder einzelne Units. Bis auf das WMCOPYDATA was zwangsläufig in der Hauptunit verankert sein muss denke ich das alles ein Gutes Ende nehmen wird, aber vielleicht finde ich ja noch einen Weg das WMCOPYDATA da auch rauszuhalten, mal sehen. Wenn es fertig ist stelle ich es unter Benutzerprojekte bereit. Einen Thread-Titel der Aussagekräftiger als ".exe zu .exe Komminukation" muss ich mir auch noch einfallen lassen ^_^ |
AW: .exe zu .exe Kommunikation
WM_COPYDATA muss nicht in der Hauptunit (Formular-Unit) verankert sein.
Du kannst Nachrichten auch empfangen mit einem eigenen unsichtbaren Fenster, was du leicht durch AllocateHWnd erstellen kannst. |
AW: .exe zu .exe Kommunikation
Ich werde heute noch zum Piraten so oft wie ich schon "ahhhhrg" schrie :))
PERFEKTER TIPP *KUSSI BUSSI* Den werde ich exakt wie beschrieben umsetzen, dann sind seperate Units Null Problemo. Vielen Dank @NG! |
AW: .exe zu .exe Kommunikation
TCP hat einen entscheidenden Nachteil: Es ist nicht unmittelbar Terminalserver tauglich. Da die Applikationen einen definierten Serverport aufmachen müssen, geht das pro Maschine nur ein Mal. Man kann das im Terminalserver wohl konfigurieren, daß der gleiche Port mehrfach vergeben werden kann, aber daran muß man denken. Hab ich vor 15 Jahren alles mal durchmachen müssen, und bin am Ende für IPC bei COM gelandet...was richtig Geil lief, aber "because of popular demand" dann doch einen Schritt zurück zu WMCOPYDATA gegangen.
Sherlock |
AW: .exe zu .exe Kommunikation
|
AW: .exe zu .exe Kommunikation
Zitat:
Das ist auch nur wieder eine Frage des Anwendungsfalles. Bei mir ist das z.B. ein systembezogener Systemdienst - damit ist es eben gerade direkt Terminalserver-tauglich, weil es, egal wie viele Sessions, nur einen "Server" gibt ;) Generell ist das mit den Ports natürlich immer ein Problem (nicht nur, wenn man über Sessions verteilt), deswegen suche ich z.B. einen freien Port innerhalb eines bestimmten Bereichs und speichere den in der Registry, damit die Client-Software-Teile das finden können. |
AW: .exe zu .exe Kommunikation
Für TCP nehme ich gerade lediglich exemplarisch localhost, im Endprodukt muss jeder Wissen was er für welchen Zweck braucht, falls überhaupt :-)
Vielleicht bastel ich auf die schnelle noch Adress+Port edit rein, mal sehen. |
AW: .exe zu .exe Kommunikation
Ich bevorzuge Memory maped Files:
Beispiel: Wir haben eine SPS deren IO's über mit einem DELPHI Programm mit einr Active X Komponente gelesen und geschrieben werden. Dieses Programm ist die Schnittstelle zu diesem Typ SPS. Wir haben ein "Labor - Analysengerät" das über eine PC-Software des Herstellers kontrolliert werden muss. Ein Delphi Programm kontrolliert dieses Programm über seine Fenster-und Control Handles. Dieses DELPHI-Programm ist die Schnittstelle zu dieser Software. :twisted:fremde Software zu vergewaltigen ist unsere Spezialität. Wir haben dann eine Handvoll weiterer Programme die jedes für sich die Daten von diesen Programmen einsammelt, verarbeitet und Bewertet. Jedes der Programme hat eine andere Aufgabe. Alle Aufgaben müssen aber aufeinander abgestimmt werden. Diese Programme tauschen untereinander einzelne Messdaten und Statusdaten aus und reagieren entsprechend. Ein zentrales Masterprogramm regelt den Gesamtablauf und greift je nach Status ein. Ein Bedienprogramm ist in der lage einzelne der Programme zu bedienen und Werte abzufragen. Es ist insgesamt ein sehr umfangreiches Projekt, doch dies über viele einzelne Programme zu regeln, hatte den Vorteil, dass sich bei Änderung eines Bestandteils der Aufgaben oder Hardware, nur das betreffende Programm angefasst werden muss. Hier agieren viele Programme miteinander, tauschen Daten aus und das mehrmals pro Sekunde. Wir haben die unterschiedlichsten Mechanismen ausprobiert, daruter Messages, Echte Dateien auf einer Memorydisk, IP-Kommunikation und sind am Ende bei den Memory Mapped Files geblieben, da diese sich am langzeitstabilsten erwiesen haben. |
AW: .exe zu .exe Kommunikation
Eine Art Performancetest sowie die Möglichkeit zur Angabe der Datengrößen die man schicken möchte in deiner Demo wäre sicher von Vorteil.
|
AW: .exe zu .exe Kommunikation
Warum benutzt Ihr nicht COM? Das ist doch genau dafür gedacht. Einen Server, einen oder mehrere Clients mit Eventsink für Kommunikation in beiden Richtungen: Delphi bietet alles an Komponenten, was man dazu braucht. Eine komfortable und sehr gut funktionierende Lösung.
|
AW: .exe zu .exe Kommunikation
Und wenn Programm.exe schon offen ist, man nochmal Programm.exe startet und nur die Parameter von der zweiten an die erste Instanz geben will? Da finde ich COM,TCP und sowas etwas übertrieben.
|
AW: .exe zu .exe Kommunikation
Ich (der TE) hatte dieses Problem, ich wollte das ein Hauptprogramm arbeitet und ein anderes Programm nur zuhört wie weit das Hauptprogramm mit Arbeit ist bzw an welcher Stelle es sich gerade befindet, ähnlich einem Debug nur viel simpler und keine Möglichkeit da einzugreifen, also kein "Chat-Programm" wo Nachricht hin und her geht sondern Einbahnstrasse.
Das Thema IPC war für mich bis dato neu sonst hätte ich garantiert weder einen Thread erstellt noch Thread-Titel so doof benannt, nun wurden mir diese und jene Varianten genannt also beschloss ich kurzerhand eine kleine Demo zu kreieren die einem alles was hier besprochen war enthält. In der DP findet man massig Beispiele wenn man weiß wonach man suchen muss, ich wusste es vorher halt nicht. Server-Seitig steht mein Konstrukt mit allen Features wie beim Bild weiter oben, Client-Seitig ist es (noch) komplizierter aber ich komme Stückchenweise voran. Teilweise beissen sich die verschiedenen Typen wenn Sie gleichzeitig laufen (Client). Bevor ich Schrottcode veröffentliche, Teste ich so gut ich kann alles was mir einfällt aus. Client zeigt mehr Info's an als die eigentlich gesandten Daten, ich glaub ich mache es mir mit dem auch einfacher indem ich den die gleiche Auswahlbox verpasse anstelle permanent nach allen Varianten aktiv zu Suchen. Spätestens in einer Woche sollte ich mit mir selbst Zufrieden sein so das ich Code freigebe. edit Client und Server kann man nur einmal starten, Reihenfolge ist egal. Server sendet nur wenn Client zuhört. Client gibt Zeit für Dauer an, deswegen Möglichkeit ein Bild zu senden/empfangen als example für Binär Daten. |
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 22:10 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