Click here to Skip to main content
15,880,956 members
Articles / Programming Languages / C#
Article

HybridService: Easily Switch Between Console Application and Service

Rate me:
Please Sign up or sign in to vote.
4.52/5 (17 votes)
26 Jun 20074 min read 93.8K   1.8K   47   19
This article shows you how to turn your console application into a hybrid application that allows you to run it as either a console application or a service via command line arguments

Screenshot - hybridservice.jpg

Introduction

Recently, I ran into a problem while developing a client/server application. I needed to turn the server (console application) into a service so that it would run when the server started, without having to log into the machine. In the past, I would have left the console application as-is, started another project as the actual service and have it launch the console application. Then I would to start yet another project to do the actual installing and uninstalling of the service. Many of you might have used a similar technique and I'm sure you can all agree that having three executable files for switching between console and service is a real pain. So, I went scouring the internet and found an excellent article by Chris Mullins which put me in the right direction.

Using the code

If you have already created the console application, you will need to move it from the Program.cs file to the ConsoleApplication.cs class provided in the demo application. This may take some work if you built your entire application in the Program.cs file. If you haven't built your application yet, you're in luck as it's very simple to use this code. I would recommend using the demo project as your new project, as everything you need is already there. All you need to do is build your application in ConsoleApplication.cs, using the constructor as you would use the entry point of Program.cs. Here is a quick example of using the ConsoleApplication.cs file:

C#
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace HybridService
{
    class ConsoleApplication
    {
        public ConsoleApplication(string applicationPath, bool consoleMode)
        {
            //This is where your console application would be

            Console.WriteLine("Hybrid Service Application");
            Console.WriteLine();

            StreamWriter stream = 
                new StreamWriter(applicationPath + "\\output.txt", true);
            stream.WriteLine(DateTime.Now.ToString("f") + "   It works! \n");
            stream.Flush();
            stream.Close();
            stream.Dispose();

            Console.WriteLine(
                "I have written to " + applicationPath + "\\output.txt");
            Console.WriteLine("Press any key to exit...");
            if (consoleMode) Console.ReadKey();

            //If you need to exit the application before 
            //it reaches this point, you need to use the line below, or 
            //the service will not stop running.
            //But if you are running a socket server or something that 
            //needs to stay alive after this method has been executed, 
            //remove the line below.
            Environment.Exit(0);
        }

        public void Close()
        {
            //Application is exiting. This is where your cleanup code 
            //should be. For example, a socket server would need 
            //"mySocketListener.Close();"
        }
    }
}

You will also need to open the Program.cs file and give your application a name that will be displayed in the Services window.

applicationTitle = "My Hybrid Service";

Running the application

If you were to start debugging this application right now, it would show up as a console window. This is great for testing and debugging, but when you're ready to move it into production as a service, you would normally need to jump through hoops. Then if you needed to debug something, you would have to jump through those hoops all over again, but not anymore! Now it is easier than ever to switch between console and service. You don't even have to change your code. All you need to do is build your project, open a Command Window, navigate to your project's Release folder, and use the following command line argument:

HybridService -service

Your program will now install the service and run it once it's installed. It has also been configured to start when your machine boots. If you need to make changes to the program, stop the service and rebuild your application. That's it. Once you're done testing it in production, you will need to uninstall the service so that it doesn't linger on your machine. Use this command line argument:

HybridService -noservice

Your service has now been stopped (if it was running) and uninstalled.

Points of interest

I personally think this is the greatest thing since sliced bread, but I'm biased. However, there are some things that you need to be aware of:

  • You cannot have spaces in your executable's name, and its extension must be .exe
  • Since you aren't running your code in a static class, you cannot use "return" or Application.Exit(). You have to use Environment.Exit(0) to end your application.
  • Avoid using Console.Read() or any other blocking calls requiring user-input. If you need to use it only in console mode, check for the consoleMode argument. The above example demonstrates this.
  • Don't use Environment.CurrentDirectory unless you want it to return the System32 folder. Use the applicationPath argument instead. Again, this is demonstrated above.
  • Before renaming or moving your executable, make sure it is NOT installed as a service!
  • You cannot install your application as a service if the executable is not on your local machine. Trying to install the service from a network drive will NOT work.
  • Another little annoying Windows'ism is that you MUST close the Services window when you uninstall the service or it will stay in the list of services until you close it. Refreshing the window will NOT work. You have to close and re-open it.

Final notes

I would, again, like to thank Chris Mullins for posting his code. As for the ServiceInstaller, it is a modified version of some code I found about a year ago. I can't remember who the original author was, but if you know, send me a link to the original code and I'll post a thank-you to him/her as well. I hope this code helps someone. It has helped me quite a bit. Also, I would appreciate some feedback. This is my first post to CodeProject, so I'm interested in learning how I did. If you find any problems, let me know. If you use this in your project, I only ask that you give me credit for it in your application.

History

  • 2007-06-22: Article posted

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
PraisePerfect perfect perfect Pin
Barış Böyükbaş1-Jan-16 23:45
Barış Böyükbaş1-Jan-16 23:45 
GeneralMy vote of 5 Pin
Chris_Inman14-Jun-12 7:32
Chris_Inman14-Jun-12 7:32 
GeneralGetting error: 'System.ServiceProcess.ServiceInstaller' does not contain a definition for 'UnInstallService' Pin
globy10-Sep-09 16:40
globy10-Sep-09 16:40 
GeneralCode Pin
dm328110-Dec-08 16:53
dm328110-Dec-08 16:53 
GeneralNice, but there is a better solution. Pin
Alexander Stuckenholz29-Jun-08 22:30
Alexander Stuckenholz29-Jun-08 22:30 
GeneralRe: Nice, but there is a better solution. Pin
Luis Perez ----- (Simply Good Code)1-May-11 5:40
Luis Perez ----- (Simply Good Code)1-May-11 5:40 
GeneralWorks Great! Pin
Norbert1712-Jun-08 6:24
Norbert1712-Jun-08 6:24 
GeneralGreat article !!! Pin
Hans-Jürgen Schmidt28-Jan-08 0:49
Hans-Jürgen Schmidt28-Jan-08 0:49 
GeneralTo anyone having a problem with service stuck at starting Pin
Ross Peoples24-Jul-07 2:23
Ross Peoples24-Jul-07 2:23 
NewsFixed! (Now it Starts) Pin
travislaborde11-Jul-07 7:40
travislaborde11-Jul-07 7:40 
GeneralRe: Fixed! (Now it Starts) Pin
Stewart Roberts11-Jul-07 10:06
Stewart Roberts11-Jul-07 10:06 
GeneralRe: Fixed! (Now it Starts) Pin
travislaborde12-Jul-07 4:56
travislaborde12-Jul-07 4:56 
QuestionRe: Fixed! (Now it Starts) Pin
Stewart Roberts12-Jul-07 8:22
Stewart Roberts12-Jul-07 8:22 
AnswerRe: Fixed! (Now it Starts) Pin
travislaborde16-Jul-07 2:10
travislaborde16-Jul-07 2:10 
GeneralService stays in "Starting" mode until the Constructor code completes Pin
JamesMMM10-Jul-07 10:44
JamesMMM10-Jul-07 10:44 
I notice if i add my code to the Console Application's constructor which basically checks for a running process, then sleeps for 2 minutes and checks again in an endless loop, the services control panel shows that the service is in starting mode and never actually gets to running. This behavior does not seem right.

James Mikelis
GeneralRe: Service stays in "Starting" mode until the Constructor code completes Pin
travislaborde11-Jul-07 7:40
travislaborde11-Jul-07 7:40 
Questionnice, but.... Pin
travislaborde10-Jul-07 9:08
travislaborde10-Jul-07 9:08 
AnswerRe: nice, but.... Pin
travislaborde11-Jul-07 7:09
travislaborde11-Jul-07 7:09 
GeneralService won't start Pin
Stewart Roberts4-Jul-07 4:49
Stewart Roberts4-Jul-07 4:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.