How to communicate with a windows service?
Asked Answered
E

9

44

I want to create a windows service that validates data and access it from another windows application, but I'm new to services and I'm not sure how to start.

So, while the service is running, a windows application should somehow connect to the service, send some data and get a response, true or false.

Essayistic answered 15/12, 2010 at 14:54 Comment(1)
Upgrade the service so it has a e.g. a REST API. Heck, perhaps even turn it into a REST API and use something else to call it periodically; better observabilityLamented
M
48

I could successfully handle the (almost) same issue as yours doing the following:

In your Class : ServiceBase, that represents your Service class, you might have:

public Class () //constructor, to create your log repository
    {
      InitializeComponent();
     
      if (!System.Diagnostics.EventLog.SourceExists("YOURSource"))
      {
        System.Diagnostics.EventLog.CreateEventSource(
           "YOURSource", "YOURLog");
      }
      eventLog1.Source = "YOURSource";
      eventLog1.Log = "YOURLog";
    }

Now, implement:

protected override void OnStart(string[] args)
{...}

AND

protected override void OnStop()
{...}

To handle custom commands calls:

protected override void OnCustomCommand(int command)
    {
      switch (command)
      {
        case 128:
          eventLog1.WriteEntry("Command " + command + " successfully called.");
          break;
        default:
          break;
      }
    }

Now, use this in the application where you'll call the Windows Service:

Enum to reference your methods: (remember, Services custom methods always receive an int32 (128 to 255) as parameters and using Enum you make it easier to remember and control your methods

private enum YourMethods
  {
    methodX = 128
  };

To call a specific method:

ServiceController sc = new ServiceController("YOURServiceName", Environment.MachineName);
ServiceControllerPermission scp = new ServiceControllerPermission(ServiceControllerPermissionAccess.Control, Environment.MachineName, "YOURServiceName");//this will grant permission to access the Service
    scp.Assert();
    sc.Refresh();

    sc.ExecuteCommand((int)YourMethods.methodX);

Doing this, you can control your service.

Here you can check how to create and install a Windows Service. More about the ExecuteCommand method.

Good luck!

Monocular answered 5/9, 2013 at 13:22 Comment(2)
Is there a way I can send something other than an int, say a string to the service? And how can I get a return value ( sent by the service) in my applicationLuminescent
@Luminescent I'm afraid that is not possible when you you this way of communicationTrista
A
7

If you are using .Net Framework 4, then memory mapped files provide a fairly easy way of implementing cross process communication.

It is fairly simple, and well described in documentation, and avoids the overhead (at runtime but also in terms of development effort) of using WCF or other connection/remoting based interactions, or of writing shared data to a central location and polling (database, file, etc).

See here for an overview.

Administrate answered 15/12, 2010 at 15:2 Comment(0)
O
3

You could accomplish this very easily by making the service host a WCF service and connecting to it from your application.

Opposite answered 15/12, 2010 at 14:58 Comment(4)
This may work, but there are a host of security implications to consider when doing this. You now have a service with an open port listening - how can you validate who is connecting? Are you protected against malicious connections? You may need to escalate permissions to NETWORK SERVICE or somesuch just to open the connection, whereas your service may not require this level of permission. Overall - I'd think carefully before implementing this if there are other, simpler, safer options.Administrate
@Rob, you don't have to make the service listen on a tcp port. WCF can use named pipes for communication between applications on the same machine. Of course if the desktop application is on another machine, you would have to have an open port but I don't think that's the case for this scenario.Breaststroke
@jlafay - fair point about named pipes - you are right, but for any connection oriented approach you will have a host of security implications to consider.Administrate
Even within the NetTcpBinding you can use the localhost address to limit access to the local machine. While security implications do arise once you cross the machine boundary, the fact remains that WCF makes distributed operation possible while a memory mapped solution precludes it.Caffrey
H
3

We use Named pipes for this purpose. But our client implemented with C++. If your service and application are implemented in .Net, you can use .Net remoting.

Heterograft answered 15/12, 2010 at 14:59 Comment(8)
.NET Remoting has been superseded by WCF.Caffrey
@Matt Davis - that it just isn't true for all remoting usage scenarios. There is no WCF equivalent of binary remoting a MarshalByRefObject object in WCF (which would potenitally be the best remoting solution to this problem). WCF superceds remoting for many use cases but not all.Administrate
@Rob Levine, while it is true there is no equivalent for the MarshalByRefObject scenario within WCF, there are still ways around this within a WCF framework. The MSDN website specifically says that .NET Remoting is a legacy technology maintained for backward compatibility and not recommended for new development. msdn.microsoft.com/en-us/library/kwdt6w2k.aspxCaffrey
@Matt Davis - Certainly for distributed applications WCF is the way forward, and this is what most people want to do with remoting. Even though the original remoting is considered legacy, I would still maintain there is a subset of functionality that cannot easily be replicated in WCF, and so WCF is not a replacement for. I'd be interested to know what you have in mind for "ways around" the lack of a MarhsalByRefObject (i.e. by reference semantics) remoting client, because the few times I've needed it, I've never found the equivalent. Having said that, I may be missing something.Administrate
@Rob Levine - msdn.microsoft.com/en-us/library/…Caffrey
@Rob Levine - Don't get me wrong. I use .NET Remoting in my current project because doing the equivalent in WCF just feels heavyweight. Still, Microsoft's official position is that WCF should be used for new development, even when the "distributed" operation simply means crossing AppDomains in the same process.Caffrey
@Matt Davis - thanks for the link - very much appreciated. I'll be looking through that in more detail, but it seems this is showing how to get similar client-activated "by reference" behaviour in WCF - which I genuinely didn't know could be done. I shall play aournd later, but thanks again.Administrate
@MattDavis And 10 years later, WCF is now superseded by gRPC.Osis
C
2

In older versions of Windows, you could configure your Windows service to interact with the desktop. This allowed you to add user interface elements directly to your service that could be presented to the user. Beginning with Windows Vista, services can no longer interact directly with users, i.e., no user interfaces.

To do this, what you want to do is write your Windows service and a front-end Windows application. To provide the communication bridge between the two, I would strongly recommend using Windows Communication Foundation (WCF).

To create a C# Windows service, you can follow the step-by-step instructions here.

Caffrey answered 15/12, 2010 at 14:59 Comment(0)
H
0

Think it as a remote database owner. Say you have 1 database yet 10 applications that requires different data's from the database and also you don't want to open all your data to each of the applications.. Also your applications will be independent from your database, your data layer will only be implemented in your service, your applications will not hold that logic. You can write a service and open your service to your other applications.

How to write your first windows service can help you.

Heraclid answered 15/12, 2010 at 15:0 Comment(0)
Z
0

What I am doing and seems to be working for my needs so far is have my windows desktop app write values to a file in the CommonApplicationData special folder using:

Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)

And then my Windows Service knows to look for the file and the values in it using the same method.

CommonApplicationData is the directory that serves as a common repository for application-specific data that is used by all users, including the SYSTEM account.

For details, see Environment.GetFolderPath Method and CommonApplicationData in Environment.SpecialFolder.

You could use any file format that suits your needs: .txt, .ini, .json, etc

Zoologist answered 2/12, 2022 at 20:33 Comment(0)
B
0

another implicit way, you can set a configuration file and change it, another application restart the service application and then the service app reloads the configuration file.

Birchard answered 4/5 at 7:44 Comment(0)
P
-2

Your service, while it is processing, can add events to the EventLog.

You can create another console application that runs paralel to the service, and that listens to that EventLog with the event handling mechanism:

var log= new EventLog("[name of the eventlog]");
log.EnableRaisingEvents = true;
log.EntryWritten += Log_EntryWritten;

Then you handle it immediately:

private static void Log_EntryWritten(object sender, System.Diagnostics.EntryWrittenEventArgs e)
{
    Console.WriteLine("Event detected !");
}

You can read the EntryWrittenEventArgs object to get all event details, and to show what you want in your console app. If you stop the console app the service continues to run, and still logs to the event log.

Phonics answered 20/12, 2018 at 14:2 Comment(1)
Sniffing the event log to transfer business data between application components is perhaps not the worst idea ever, but it comes close.Yore

© 2022 - 2024 — McMap. All rights reserved.