1

I'm quite new to development of Windows Services (my background is in Web Development) and I'm a bit confused by the development process for Windows Services.

As I understand it, the service has to be installed every time you compile the code, and then run from the Services MMC snapin.

This seems like an awfully painful process to go through every time you make a change to your code.

Can someone shed some light on the 'recommended' approach for building services?

Thanks

Michael Bates
  • 1,884
  • 2
  • 29
  • 40

3 Answers3

1

To debug services, I generally use the following boilerplate for Main:

static void Main()
{
    ServiceBase[] servicesToRun = new ServiceBase[] { new MyService(); };

#if !DEBUG
    //run the service normally using ServiceBase.Run
    ServiceBase.Run(servicesToRun);
#else
    //debug the process as a non-service by invoking OnStart and then sleeping

    foreach (ServiceBase s in servicesToRun)
    {
        var serviceType = s.GetType();
        var onStartMethod = serviceType.GetMethod("OnStart", System.Reflection.BindingFlags.Instance | 
            System.Reflection.BindingFlags.NonPublic);
        onStartMethod.Invoke(s, new object[] { new string[0] });
    }
    Debug.WriteLine("done starting services");
    while (true)
        Thread.Sleep(200);
#endif
}

What this does is use reflection to get the OnStart protected method for each service, invoke it, then sit in a sleep loop to keep the process running.

This example is assuming MyService is the service class that inherits from ServiceBase, which overrides OnStart to spawn off thread(s) and do its thing.

Here I'm using the DEBUG compile-time constant as the controlling factor of whether to start normally or debug as a non-service. If DEBUG is defined it will run in-process as a non-service. Otherwise it does its normal thing calling ServiceBase.Run. Feel free to use a command-line argument or whatever works best for you.

lc.
  • 113,939
  • 20
  • 158
  • 187
0

You may need some tweaks or re-factoring most of the logic to console app for easier testing, debugging, as what comes out of the box is really painful.

Here are some resources :

http://candordeveloper.com/2012/12/27/debugging-a-windows-service-application-without-install/

Running Windows Service Application without installing it

the easiest of them might be putting 
#if DEBUG
   //your logic
#endif
in your logic, putting a breakpoint and hitting F5, this is what i do most of the time.

Would be interesting to know if there is even better ways :)

Community
  • 1
  • 1
Bravo11
  • 898
  • 2
  • 11
  • 24
0

Answers from Bravo 11 and Ic. give some good tips and tricks. I will add some:

Be aware that running as as service has also some implications regarding login / security context:

  • running under SYSTEM, you cannot access network file shares normally (there is a way adding the machine account to the ACL however)

  • running under a (domain) user account needs "logon as service" privileges, which is IMHO the most common cause of service starting problems in enterprise environments (the GPO settings may be adjusted). In addition, you do not have access to the desktop, so if a popup will be displayed waiting for the user, the service hangs.

  • in the development phase, you can swap DLLs or even the EXE if the service is not currently running without uninstall / install

  • use Windows event log extensively.

These differences between services and "normal application" are important enough for me to let this run directly on a server as often as possible.

In my services, I use:

protected override void OnStart(string[] args)
{
    // this is not just a simple message, this has to be called very early before any worker thread
    // to prevent a race condition in the .NET code of registering the event source
    EventLog.WriteEntry("XXXXService is starting", EventLogEntryType.Information, 1000);

....

And do not forget that OnStart() and OnStop()should not contain long running code. You normally start a worker thread in OnStart() which runs until some notification (set in OnStop) was triggered.

Rainer Schaack
  • 1,558
  • 13
  • 16