I have recently stated working with .NET Windows Services (again) after a year long break from them, and any developer who has worked with them before will tell you how much effort is involved in debugging a .NET windows service.
In short the basic principle is…
- Run Service
- Attach Visual Studio Debugger
…as simple as this seems there is an awful lot of mouse clicking involved.
Also debugging the service as it is strating up is problematic, so I place a simple wait to give me the opportunity to debug start-up code such as…
#if DEBUG
// give us a chance to attach the debugger
Thread.Sleep(10 * 1000);
#endif
… so i have a chance to get my debugger attached in time. However the number of times I’ve made mistakes like attaching to the wrong process or have run out of time is countless.
So below is a Macro I wrote to auto-magically attach to the service I wish to debug in question. This code will also stop and re-run the service in question if already running so you have a chance to grab the start-up code.
To Install:
- Open the Visual Studio “Macros IDE” (Alt-F11).
- Add a new code file.
- Add a reference to System.ServiceProcess
- Paste contents of below script.
- Add your .NET Windows Service short name and EXE name in the constant variables.
- Run the macro.
Option Strict Off
Option Explicit Off
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics
Imports System.ServiceProcess
Public Module Scheduler
Private Const ServiceName As String = ""
Private Const SeviceEXE As String = ".exe"
' Used to start the service on a seperate thread.
Delegate Sub StartServiceWorker()
'stop the service
Sub StopService()
Dim schedulerService As ServiceController
schedulerService = New ServiceController(ServiceName)
If schedulerService.Status = ServiceControllerStatus.Running Then
schedulerService.Stop()
End If
End Sub
' starts and attached to the scheduler
Sub StartAndAttachToScheduler()
StartService()
' wait 1 second so service starts.
Threading.Thread.Sleep(1000)
AttachToScheduler()
End Sub
' Starts the service on a seperate thread.
Private Sub StartService()
Dim myStartService As New StartServiceWorker(AddressOf StartServiceHelper)
myStartService.BeginInvoke(Nothing, Nothing)
End Sub
' Starts the service (will stop first if already running)
Private Sub StartServiceHelper()
Dim schedulerService As ServiceController
schedulerService = New ServiceController(ServiceName)
If schedulerService.Status = ServiceControllerStatus.Running Then
schedulerService.Stop()
End If
schedulerService.Start()
schedulerService = Nothing
End Sub
' This subroutine attaches to calc.exe if it is running.
Private Sub AttachToScheduler()
Dim attached As Boolean = False
Dim proc As EnvDTE.Process
For Each proc In DTE.Debugger.LocalProcesses
If (Right(proc.Name, SeviceEXE.Length) = SeviceEXE) Then
proc.Attach()
attached = True
Exit For
End If
Next
If attached = False Then
MsgBox(String.Format("{0} is not running", ServiceName))
End If
End Sub
End Module
Hope this now makes working with services now a little easier for all.