UPDATE
This approach is by far the easiest:
http://www.codeproject.com/KB/dotnet/DebugWinServices.aspx
I leave my original answer below for posterity.
My services tend to have a class that encapsulates a Timer as I want the service to check at regular intervals whether there is any work for it to do.
We new up the class and call StartEventLoop() during the service start-up. (This class could easily be used from a console app too.)
The nice side-effect of this design is that the arguments with which you set up the Timer can be used to have a delay before the service actually starts working, so that you have time to attach a debugger manually.
p.s. How to attach the debugger manually to a running process...?
using System;
using System.Threading;
using System.Configuration;
public class ServiceEventHandler
{
Timer _timer;
public ServiceEventHandler()
{
// get configuration etc.
_timer = new Timer(
new TimerCallback(EventTimerCallback)
, null
, Timeout.Infinite
, Timeout.Infinite);
}
private void EventTimerCallback(object state)
{
// do something
}
public void StartEventLoop()
{
// wait a minute, then run every 30 minutes
_timer.Change(TimeSpan.Parse("00:01:00"), TimeSpan.Parse("00:30:00");
}
}
Also I used to do the following (already mentioned in previous answers but with the conditional compiler [#if] flags to help avoid it firing in a Release build).
I stopped doing it this way because sometimes we'd forget to build in Release and have a debugger break in an app running on a client demo (embarrasing!).
#if DEBUG
if (!System.Diagnostics.Debugger.IsAttached)
{
System.Diagnostics.Debugger.Break();
}
#endif