C# Converting Console App to Service

user2892443 picture user2892443 · Oct 18, 2013 · Viewed 14.5k times · Source

I am trying to convert a console app to a Windows service. I am trying to have the onstart method of the service call a method in my class but I can;t seem to get it to work. I'm not sure I am doing this correctly. Where do I put the class information in the service

protected override void OnStart(string[] args)
{
   EventLog.WriteEntry("my service started");
   Debugger.Launch();
   Program pgrm = new Program();
   pgrm.Run();
}

From the comment:

namespace MyService {
 static class serviceProgram {
  /// <summary> 
  /// The main entry point for the application. 
  /// </summary> 
  static void Main() {
   ServiceBase[] ServicesToRun;
   ServicesToRun = new ServiceBase[] {
    new Service1()
   };
   ServiceBase.Run(ServicesToRun);
  }
 }
}

Answer

ChrisO picture ChrisO · Oct 18, 2013

The MSDN documentation on Windows Services is really good and has everything you need to get started.

The problem you're having is because of your OnStart implementation, that's only supposed to be used to set up the service so it's ready to start, the method must return promptly. Usually you'd run the bulk of the code on another thread or in a timer. See the page for OnStart for confirmation.

Edit: Without knowing what your windows service will do, it's hard to tell you how to implement it but let's say you wanted to run a method every 10 seconds while the service is running:

public partial class Service1 : ServiceBase
{
    private System.Timers.Timer _timer; 

    public Service1()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
#if DEBUG
        System.Diagnostics.Debugger.Launch(); // This will automatically prompt to attach the debugger if you are in Debug configuration
#endif

        _timer = new System.Timers.Timer(10 * 1000); //10 seconds
        _timer.Elapsed += TimerOnElapsed;
        _timer.Start();
    }

    private void TimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
    {
        // Call to run off to a database or do some processing
    }

    protected override void OnStop()
    {
        _timer.Stop();
        _timer.Elapsed -= TimerOnElapsed;
    }
}

Here, the OnStart method returns immediately after setting up the timer and TimerOnElapsed will be run on a worker thread. I also added a call to System.Diagnostics.Debugger.Launch(); which will make debugging alot easier.

If you have some other requirements, please edit your question or post a comment.