2009-08-11 4 views
5

Wie kann eine Desktop-Anwendung mit einem Windows-Dienst unter Vista/Windows2008/Windows7 kommunizieren? Die Anwendung muss dem Service kleine Zeichenfolgen senden und Zeichenfolgenantworten empfangen. Beide sind in Delphi 2009 geschrieben. (Bitte geben Sie auch Beispielcode ein)Delphi 2009: Wie kommuniziert man zwischen Windows Service & Desktop-Anwendung unter Vista?

+0

Es ist erstaunlich! Ich habe fast die gleiche Frage gestellt und ich war auch bescheidener, aber ich habe nur Kritik statt Antworten ... ;-) – PSyLoCKe

Antwort

6

Der Weg zu gehen ist named pipes, werden Sie wahrscheinlich einen Blick auf die Kommunikation über verschiedene Integrity levels zu nehmen.

This article untersucht, wie dies in Vista zu tun. Obwohl es in C++ geschrieben ist, sind es nur einfache Windows-API-Aufrufe, daher sollte es schnell genug nach Delphi übersetzt werden.

Wenn Sie mehr zu diesem Thema suchen möchten, wird diese Kommunikation Inter Process Communication genannt, aber ein besserer Suchbegriff ist IPC.

+1

Ist das absolut wahr? Ich habe mehrere Windows-Dienste als TCP-Server und TCP-Client ausgeführt. Sie sind alle als "lokales System" in Ordnung. Ich habe immer geglaubt, dass die Beschränkung auf Netzwerkressourcen (// machine/resource/...) ist. –

+1

Die erste Behauptung ist völlig falsch. Jeder Windows-Dienst, den ich je geschrieben habe, war irgendwie ein Netzwerk-Daemon. Die einzige Zeit, in der Funky-Berechtigungen benötigt wurden, war eine, die auch UI anzeigen konnte. –

+0

Ja, ich erinnere mich falsch, es ist nicht erlaubt, eine Netzwerkverbindung zu externen Ressourcen zu erstellen, oder Sie müssen als NetworkService ausgeführt werden. Ich habe die erste Behauptung gelöscht. Aber, Named Pipes sind eine bessere Möglichkeit, mit Ihrem Dienst zu kommunizieren (Problem beim Lokalisieren des Vista-Kompatibilitätsartikels über IPC) –

2

Ich habe es nicht versucht, aber ich denke, Sie könnten Named Pipes verwenden.

3

Werfen Sie einen Blick auf die Antworten in Exchange Data between two apps across PC on LAN, die heutzutage ziemlich die gleiche Frage ist. Lokale Kommunikation über TCP ist Standard. Wie ich in meiner Antwort dort sagte, funktionieren Lösungen, die Schnittstellen vom Typ "Remote Procedure Call" verwenden, gut. Ich benutze RemObjects SDK für diese Art von Sache, und es macht es leicht zu erweitern, um über das Netzwerk zu steuern, wenn Sie später wünschen.

Beide ermöglichen es Ihnen, eine Verbindung zu erstellen, die für den Großteil Ihres Codes "transparent" ist, und Sie rufen einfach eine Schnittstelle auf, die die Daten über die Leitung sendet und die Ergebnisse zurückerhält. Sie können dann programmieren, wie Sie normalerweise tun, und die Details von Sockets etc. vergessen.

+1

Muss ein Dienst keine speziellen Berechtigungen haben, um das Netzwerk zu nutzen, auch wenn Es hört nur lokal zu? –

+0

@Rob, es hängt davon ab, auf welchem ​​Konto der Dienst ausgeführt wird. – Kevin

+0

Ich hatte keine Probleme mit RemObjects mit dem Systemkonto oder einem Benutzerkonto. Das Problem bezieht sich mehr auf Domänenbenutzerrechte als TCP/IP-Socket-Zugriff, der unabhängig ist. – mj2008

5

Mit Indy können Sie relativ einfach eine TCP-Verbindung zwischen Ihren Apps erstellen. Vor allem, wenn Sie nur String-Nachrichten senden müssen. Für die Kunden (in Ihrem Fall der Desktop-Anwendung) es ist im Grunde

var 
    Client : TIdTCPClient; 
... 
Client.Host := 'localhost'; 
Client.Port := AnyFreePortNumber; 
Client.Connect; 
Client.IOHandler.Writeln (SomeString); 
Response := Client.Readln; 
... 
Client.Disconnect; 

für den Server (würde der Dienst in Ihrem Fall sein)

var 
    Server : TIdTCPServer; 
    Binding : TIdSocketHandle; 
... 
Server.DefaultPort := SameFreePortNumberAsInClient; 
Binding := Server.Bindings.Add; 
Binding.IP := '127.0.0.1';  
Binding.Port := Server.DefaultPort; 
Server.OnConnect := HandleConnection; 
Server.OnDisconnect := HandleDisconnection; 
Server.OnExecute := HandleCommunication; 
Server.Active := True; 

einfach die HandleCommunication Methode implementieren. Es wird immer dann aufgerufen, wenn der Kunde beschließt, etwas zu senden. Beispiel:

procedure MyClass.HandleCommunication (AContext : TIdContext); 
var 
    Request : String; 
begin 
    Request := AContext.Connection.IOHandler.Readln; 
    if (Request = Command1) then 
    HandleCommand1 
    else if (Request = Command2) then 
    HandleCommand2 
    ... 
end; 

IIRC ein Dienst nur eine grafische Benutzerschnittstelle zu haben, erlaubt oder der Netzzugang hat, so könnte dies ein Problem sein, wenn Ihr Dienst eine grafische Benutzeroberfläche benötigt (die man sowieso vermeiden sollte, finden Sie in diesen question). Ich weiß nicht, wie das in Windwos Vista und später gehandhabt wird.

3

Sie müssen den Dienstbenutzer von Localsystem in networkservice ändern, und dann kann der Dienst TCPIP in Ordnung verwenden. Ich habe mehrere Dienste, die TCPIP für einen externen Kontrollhaken verwenden. Stellen Sie nur sicher, dass Ihr Service-Port konfigurierbar ist, so dass Sie mit Kollisionen umgehen können.

Einige meiner Steuerschnittstellen basieren auf XML-Seiten, die von einem internen HTTP-Server bereitgestellt werden. Dadurch kann ich den Status des Dienstes über einen beliebigen Webbrowser, der den Port auf diesem Computer erreichen kann, remote überprüfen. Der Vorteil der Verwendung von HTTP gegenüber anderen Methoden besteht darin, dass es gut funktioniert, wenn Sie mit vorhandener Netzwerkhardware arbeiten müssen.

Wenn Sie nur lokal kommunizieren, dann Named Pipes, mail slots or a memory mapped file könnte die beste Methode sein.

+0

Sie müssen das NetworkService-Konto nicht nur zur Verwendung von TCP verwenden. Es funktioniert auch gut mit LocalSystem und LocalService-Konten. –

1

Ich benutze in meinen Serviceanwendungen einen Komponentensatz, Freeware mit dem Quellcode Simple IPC.

Suche torry.net. Es hat in allen meinen Service-Apps bei der Kommunikation mit einer Desktop-App sehr gut funktioniert.

John

Verwandte Themen