How can a desktop application communicate with a Windows service under Vista/Windows2008/Windows7? The application needs to send small strings to the service and receive string responses back. Both are written in Delphi 2009. (Please provide sample code also)
views:
1523answers:
6Have a look at the answers in Exchange Data between two apps across PC on LAN which is pretty much the same question nowadays. Local comms via TCP is standard. As I said in my response there, solutions that use "Remote Procedure Call" type interfaces work well. I use RemObjects SDK for this sort of thing, and it makes it easy to expand to control across the network if you wish to later.
Both of these allow you to create a connection that for most of your code is "transparent", and you just call an interface which sends the data over the wire and gets results back. You can then program how you usually do, and forget the details of sockets etc.
Using Indy you can relatively easy create a TCP connection between your apps. Especially if you only need to send string messages. For the client (in your case the desktop application) it's basically
var
Client : TIdTCPClient;
...
Client.Host := 'localhost';
Client.Port := AnyFreePortNumber;
Client.Connect;
Client.IOHandler.Writeln (SomeString);
Response := Client.Readln;
...
Client.Disconnect;
For the server (would be the service in your case)
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;
Just implement the HandleCommunication method. It is called whenever the client decides to send something. Example:
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 a service is only allowed to have a graphical user interface OR have network access, so this might be a problem if your service needs a GUI (which you should avoid anyway, see this question). I don't know how this is handled in Windwos Vista and later though.
The way to go is named pipes, you'll probably have to take a look at the communication across different Integrity levels.
This article explores how to do this in vista. Although it's written in c++ it's just basic Windows API calls, so it should translate fast enough to Delphi.
If you want to search for more on this subject, this communication is called Inter Process Communication, but a better search term is IPC.
You have to change the service user from localsystem to networkservice and then the service can use TCPIP fine. I have several services which use TCPIP for an external control hook. Just make sure your service port is configurable so you can handle any collisions.
A few of my control interfaces are based on XML pages served from an internal HTTP server. This allows me to remotely check on status of the service using any web browser which can reach the port on that machine. The advantage of using HTTP over other methods is that it works well when you need to work over existing network hardware.
If your ONLY going to be communicating locally, then named pipes, mail slots or a memory mapped file might be the best method.