views:

403

answers:

5

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?

+3  A: 
Miky Dinescu
+1  A: 

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?

http://stackoverflow.com/questions/390307/windows-service-vs-scheduled-task

Mark Ransom
I've been thinking about that, too, yes - but then I have a web app, a bunch of SQL jobs, a bunch of Windows service, a bunch of command line tools, and now a bunch of those being used as scheduled tasks.... I'm actually trying to REDUCE the number of different types of things I need to take care of and manage. Thanks for the input anyway!
marc_s
I have successfully created applications that can be run from a command line and also installed and run as windows services but I agree with @Mark Ransom in at least the fact that they are very different beasts and that you have to be careful with the implementation - especially with the Service. Like I mentioned in the code comments in my example, don't run any blocking tasks from the OnStart event handler. Rather, start your service on a separate thread or some similar asynchronous construct!
Miky Dinescu
+1  A: 

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);
   }
i_like_caffeine
+1  A: 

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.)

juhan_h
A: 

I used the method in this SO answer. Worked like a champ.

Moose