views:

176

answers:

4

I have a project that is deployed to production as a windows service. However for local development purposes it would be useful to run it as a console application. At the moment I have a class Called ReportingHost that provides my core functionality, And a class called ReportingServiceHost that inherits from ServiceBase and allows me to run the application as a service. There is also a program class with a main method that calls ServiceBase.Run on my ReportingServiceHost.

I think I need to write a ReportingConsoleHost class that allows me to run the functionality in a console. Then I need to modify my Main to react to a command line switch and choose one or the other. These are the two bits I am having trouble with.

I have had a look at this and attempted to use that code but my app exits immediately, it doesn't show a console window and it doesn't wait for Enter before closing.

Part of the problem is that I dont have a deep understanding of how these things work. a definitive pattern for splitting my functionality, my two different ways of running that functionality, and a main method that chooses one of these ways based on a command line argument is what I am hoping to achieve.

+6  A: 

I suspect your test project was configured as a windows exe, not a console exe. With a windows exe Console.ReadLine will return immediately.

To have a console exe that works both as a service and at the command line, start it as a service project (in Visual Studio) - and add a check on Environment.UserInteractive - i.e.

static void Main() {
    if(Environment.UserInteractive) {
        // code that starts the listener and waits on ReadLine
    } else {
        // run the service code that the VS template injected
    }
}

You can of course also use a command line switch. I have example on microsoft.public.dotnet.languages.csharp that acts as:

  • an installer / uninstaller
  • a service
  • a console-mode app

depending on the switches

Marc Gravell
To make VS spawn a Console windows for you when you hit F5 with this solution, you have to change the Project properties, under Application tab set Output to Console application. As far as i can tell it will still let it self install as a service just fine as well.
Carl Hörberg
@Carl... yes, I stated "console exe" in the reply...
Marc Gravell
+2  A: 

I have done this before by implementing a normal Windows Service (by deriving from ServiceBase), but putting a check in the main method to check for a command line argument.

If the args contain /console, start the console version, otherwise start the service.

Something like this:

internal class MyService : ServiceBase
{
    internal static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            // run as a service....
            ServiceBase[] servicesToRun = new ServiceBase[] {new MyService()};
            Run(servicesToRun);
        }
        else
        {
            // run as a console application....
        }
    }
}

adrianbanks
+2  A: 

My advise? Put all your logic for your service in a separate assembly. (A class library or DLL.) Then create one project as service which references your class library and puts the code to use as services. Create a second console project which also references your class library but which will make it available as a console application. You would end up with three different projects in your solution but it does allow you to keep things separate. Actually, this would make it possible to extend your service in several other shapes too. You could, for example, create a 4th project as a web service and thus call your service from a web browser on a client system. Because the software logic is separated from the usage logic, you gain lots of control over it.

Be aware that a service will possibly run with more limitations than a console application. In general, services don't have network access by default, don't have a monitor assigned to them to display error messages and in general run with a limited user account or system account. Your service might work as a console yet fail as a service because of this.

Workshop Alex
+1  A: 

There are already two good answers above - but I thought I'd post a link to Brian Noyes' Debuggable Self-Host Windows Service Project blog post - it talks about WCF but should apply to any 'Windows Service'.

The best thing is the sample code - if you can't figure out where the above examples 'fit', grab the complete project and see how it works. Thanks Brian!

CraigD