Tutorial :How to make windows service application so it can run as a standalone program as well?



Question:

I'll start with an example: Apache web server (under Windows) has a nice feature: it can be both run as a standalone application (with current users privileges), and that it can be installed and run as a windows service directly (as local system account), using same executable.

In order for application to be run as a standalone app, all it needs to do is along the lines of having static public Main() in some public class.

In order for application to be installable and runnable as service, it has to implement ServiceBase and Installer classes in certain way. But, if application like this is run as standalone app, it will show message box.

How can this Apache-like mode of operation be achieved? I believe solution is simple, but I don't really have an idea where to start.

Piece of code that follows is used to invoke service. Can it be modified to allow standalone usage?

static class Program  {      /// <summary>      /// The main entry point for the application.      /// </summary>      static void Main()      {          ServiceBase[] ServicesToRun;          ServicesToRun = new ServiceBase[]           {               new Service() // defined elsewhere as Service : ServiceBase          };          ServiceBase.Run(ServicesToRun);      }  }  

My language of choice is C#.

Edit: Currently, I have abstracted common code into separate assembly (let's call it Library.dll), and I have two executables: Console.exe and Service.exe, which are standalone and windows service applications, respectively, and both are just means to invoking Library.dll.

My goal is to merge those two executables into one, that will still call to Library.dll.


Solution:1

In C#, an easy way to do it is to require a command line argument to run it as a service. If the argument isn't there, then run your form/console app. Then just have your installer include the argument in the executable path when installing the service so it looks like so:

C:\MyApp\MyApp.exe -service  

It would look something like this:

static void Main(string[] args)  {      foreach (string arg in args)      {          //Run as a service if our argument is there          if (arg.ToLower() == "-service")          {              ServiceBase[] servicesToRun = new ServiceBase[] { new Service1() };              ServiceBase.Run(servicesToRun);              return;          }      }        //Run the main form if the argument isn't present, like when a user opens the app from Explorer.      Application.Run(new Form1());  }  

This is just an example to give you an idea, there are probably cleaner ways to write this code.


Solution:2

After some digging, I have finally looked under .NET hood (System.ServiceProcess.ServiceBase.Run method), only to find that it checks Environment.UserInteractive bool to make sure that executable is NOT run interactively.

Oversimplified solution that works for me:

class Program  {      static void Main(string[] args)      {          if (!Environment.UserInteractive)          {              ServiceBase[] ServicesToRun;              ServicesToRun = new ServiceBase[]               {                   // Service.OnStart() creates instance of MainLib()                   // and then calls its MainLib.Start() method                  new Service()              };              ServiceBase.Run(ServicesToRun);              return;          }            // Run in a console window          MainLib lib = new MainLib();          lib.Start();          // ...      }  }  


Solution:3

You should really have all of your functionality abstracted in a library. The fact that it happens to be run from a Windows Service should not matter. In fact, if you had a faced class called ServiceFrontEnd that had a Start() and Stop() - the Windows Service application could call that, and so could a command-line app, a windows app, or whatever.

What you're describing here just needs more abstraction. The functionality of "the service" doesn't need to be tightly-coupled to how a Windows Service happens to operate. hope that helps


Solution:4

In the example you site, I'm pretty confident the Apache app is written in C or C++. For that, you would need a ServiceMain function. If you execute it like a normal program, main gets called. If you point the service control manager at it, ServiceMain gets called instead.

Regarding C#, can't say I know about that. If I had to write a service in c#, I suppose I would start here - http://msdn.microsoft.com/en-us/library/bb483064.aspx


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »