41

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.

Doug L.
  • 2,676
  • 1
  • 19
  • 33
Alexandru Pupsa
  • 1,798
  • 4
  • 21
  • 40

8 Answers8

43

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!

ascpixi
  • 529
  • 4
  • 13
user2750836
  • 431
  • 4
  • 2
  • 4
    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 application – mrid May 12 '20 at 18:55
  • @mrid I'm afraid that is not possible when you you this way of communication – Ondra Starenko Nov 25 '20 at 09:30
6

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.

Rob Levine
  • 40,328
  • 13
  • 85
  • 111
3

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

poindexter12
  • 1,775
  • 1
  • 14
  • 20
  • 1
    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. – Rob Levine Dec 15 '10 at 15:09
  • 2
    @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. – Jeff LaFay Dec 15 '10 at 15:16
  • @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. – Rob Levine Dec 15 '10 at 15:18
  • 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. – Matt Davis Dec 15 '10 at 18:28
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.

Community
  • 1
  • 1
Matt Davis
  • 45,297
  • 16
  • 93
  • 124
2

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.

DReJ
  • 1,966
  • 15
  • 14
  • 1
    .NET Remoting has been superseded by WCF. – Matt Davis Dec 15 '10 at 15:08
  • @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. – Rob Levine Dec 15 '10 at 15:12
  • @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. http://msdn.microsoft.com/en-us/library/kwdt6w2k.aspx – Matt Davis Dec 15 '10 at 18:19
  • 1
    @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. – Rob Levine Dec 15 '10 at 22:17
  • @Rob Levine - http://msdn.microsoft.com/en-us/library/aa730857(VS.80).aspx#netremotewcf_topic6 – Matt Davis Dec 16 '10 at 01:06
  • @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. – Matt Davis Dec 16 '10 at 01:16
  • @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. – Rob Levine Dec 16 '10 at 09:52
  • @MattDavis And 10 years later, WCF is now superseded by gRPC. – Mike Lowery May 15 '20 at 18:10
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.

Pabuc
  • 5,528
  • 7
  • 37
  • 52
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

Gary Barrett
  • 1,764
  • 5
  • 21
  • 33
-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.

Allie
  • 1,081
  • 1
  • 13
  • 17
  • 7
    Sniffing the event log to transfer business data between application components is perhaps not the worst idea ever, but it comes close. – Rolf Aug 09 '19 at 21:24