Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a combo command line / Windows service app

What's the best way in C# to set up a utility app that can be run from the command line and produce some output (or write to a file), but that could be run as a Windows service as well to do its job in the background (e.g. monitoring a directory, or whatever).

I would like to write the code once and be able to either call it interactively from PowerShell or some other CLI, but at the same time also find a way to install the same EXE file as a Windows service and have it run unattended.

Can I do this? And if so: how can I do this?

like image 517
marc_s Avatar asked Apr 30 '09 21:04

marc_s


People also ask

How do I create a Windows service from the command line?

The SC Create command uses the following format: sc create serviceName binpath= "path\to\service-wrapper-7.4.exe" optionName= optionValue ... where: create is the command to be run by SC (this command name is mandatory to create a service).

How do I run a service app from the command line?

You can also open Services from the Command Prompt or PowerShell. Type the command services. msc and press Enter on your keyboard.


4 Answers

Yes you can.

One way to do it would be to use a command line param, say "/console", to tell the console version apart from the run as a service version:

  • create a Windows Console App and then
  • in the Program.cs, more precisely in the Main function you can test for the presence of the "/console" param
  • if the "/console" is there, start the program normally
  • if the param is not there, invoke your Service class from a ServiceBase


// Class that represents the Service version of your app
public class serviceSample : ServiceBase
{
    protected override void OnStart(string[] args)
    {
        // Run the service version here 
        //  NOTE: If you're task is long running as is with most 
        //  services you should be invoking it on Worker Thread 
        //  !!! don't take too long in this function !!!
        base.OnStart(args);
    }
    protected override void OnStop()
    {
        // stop service code goes here
        base.OnStop();
    }
}

...

Then in Program.cs:


static class Program
{
    // The main entry point for the application.
    static void Main(string[] args)
    {
        ServiceBase[] ServicesToRun;

    if ((args.Length > 0) && (args[0] == "/console"))
    {
        // Run the console version here
    }
    else
    {
        ServicesToRun = new ServiceBase[] { new serviceSample () };
        ServiceBase.Run(ServicesToRun);
    }
}

}

like image 121
Mike Dinescu Avatar answered Oct 13 '22 03:10

Mike Dinescu


The best way to accomplish this from a design standpoint is to implement all your functionality in a library project and build separate wrapper projects around it to execute the way you want (ie a windows service, a command line program, an asp.net web service, a wcf service etc.)

like image 38
juhan_h Avatar answered Oct 13 '22 03:10

juhan_h


Yes it can be done.

Your startup class must extend ServiceBase.

You could use your static void Main(string[] args) startup method to parse a command line switch to run in console mode.

Something like:

static void Main(string[] args)
{
   if ( args == "blah") 
   {
      MyService();
   } 
   else 
   {
      System.ServiceProcess.ServiceBase[] ServicesToRun;
      ServicesToRun = new System.ServiceProcess.ServiceBase[] { new MyService() };
      System.ServiceProcess.ServiceBase.Run(ServicesToRun);
   }
like image 3
eodonohoe Avatar answered Oct 13 '22 02:10

eodonohoe


A Windows Service is quite different from a normal Windows program; you're better off not trying to do two things at once.

Have you considered making it a scheduled task instead?

windows service vs scheduled task

like image 1
Mark Ransom Avatar answered Oct 13 '22 01:10

Mark Ransom