oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Debugging Windows Services

by Wei-Meng Lee, author of Windows XP Unwired

As I mentioned in my last article on Developing Windows Services, debugging Windows services is not as trivial as debugging Windows applications because they do not run directly within Visual Studio .NET. Hence, more elaborate techniques must be deployed to effectively develop and debug Windows services. In this article, I will discuss two techniques that you can use to debug and test your Windows services.

Method 1: Attaching a Debugger

The first method to debug a Windows service is to attach a debugger to a running service. You can then set breakpoints to cause the Windows service to suspend, giving you the ability to step through the code. Let's see how we can do this using the sample TimeService Windows service illustrated in my last article.

First, you need to install your Windows service. (You can refer to my last article for the steps to install a Windows service.) After installation, start the service either using the Services manager (located in Control Panel, Administrative Tools), or the command line.

In Visual Studio .NET 2003, set a breakpoint at the statement that you wish to step through (see Figure 1).

Setting a breakpoint in Visual Studio .NET 2003
Figure 1: Setting a breakpoint in Visual Studio .NET 2003

Now, select the menu item Debug->Processes...(see Figure 2) to invoke the Processes window (see Figure 3).

Invoking the Processes window
Figure 2: Invoking the Processes window

In the Available Processes group (see Figure 3), locate the service that you want to debug (TimeService.exe in my case); select it and click the Attach... button.

Attaching the debugger to a process in the Processes window
Figure 3: Attaching the debugger to a process in the Processes window

The Attach to Process window will appear. Click OK and then the Close button on the Processes window. You are now in debugging mode.

Because the listener.AcceptTcpClient() method (which I used in my Windows service) is a blocking call, my Windows service will only break for debugging when a client sends an incoming message. So, execute your client (use the sample console application from my last article), and send a message to the service so that we can proceed with the debugging.

Assuming that you've received an incoming message, the Windows service should now be pending at the breakpoint (see Figure 4).

Visual Studio .NET displaying the paused breakpoint
Figure 4: Visual Studio .NET displaying the paused breakpoint

You can now perform the usual debugging procedures, such as running QuickWatch, Step Into, Step Out, and Step Over operations.

You can also set breakpoints at the OnStop(), OnPause(), and OnContinue() methods and observe what happens when the service stops, pauses, and continues, respectively.

Downsides of Using the Debugger

Related Reading

Programming .NET Web Services
By Alex Ferrara, Matthew MacDonald

The main problem with using the debugger in Visual Studio .NET 2003 is that you can't debug the OnStart() method; neither can you debug the Main method. This is because you can only attach a debugger to a service after it has started running, which by then, the OnStart() method has already completed its execution and returned the control to the operating system. There are workarounds to debugging the OnStart() method (as documented in MSDN), but even if you could debug the OnStart() method, you have only 30 seconds to step through the code in the method as the Windows Service Manager imposes a 30-second limit on all attempts to start a service.

My suggestion would be to minimize the number of statements in the OnStart() method and move the bulk of the work to a subroutine or a function. By doing so, you can then set your breakpoints in the subroutine and not in the OnStart() method.

It's a tedious task to debug a Windows service after it has started running, so I recommend the second method, as described in the next section.

Method 2: Encapsulating the Service Logic in a Class

In this second method, a better way to debug Windows services is to test the logic of the Windows service independently, preferably as a console or Windows application. The idea is to contain the service logic as an independent unit, ideally in a DLL.

In this section, I will create a class (project name TimeServiceClass) to store the application logic of the TimeService Windows service.

Here is the full source for the class:

Imports System.Net.Sockets
Imports System.Net
Imports System.Text

Public Class TimeService

  Private canStopListening As Boolean = False
  Private pause As Boolean = False

  Public Sub startService()
  End Sub

  Public Sub pauseService()
    pause = True
  End Sub

  Public Sub continueService()
    pause = False
  End Sub

  Public Sub stopService()
    canStopListening = True
  End Sub

  Private Sub Listen()
    Const portNo As Integer = 500
    Dim localAdd As System.Net.IPAddress = _
    Dim listener As New TcpListener(localAdd, portNo)
      If Not pause Then
        Dim tcpClient As TcpClient = listener.AcceptTcpClient()
        Dim NWStream As NetworkStream = tcpClient.GetStream
        Dim bytesToRead(tcpClient.ReceiveBufferSize) As Byte
        '---read incoming stream
        Dim numBytesRead As Integer = _
            NWStream.Read(bytesToRead, 0, _
        '---write to console
        Console.WriteLine("Received :" & _
          Encoding.ASCII.GetString(bytesToRead, _
          0, numBytesRead) & " @ " & Now)
        '---write time back to client
        Dim time() As Byte = _
        NWStream.Write(time, 0, time.Length)
      End If
    Loop Until canStopListening = True
  End Sub
End Class

Basically, I have encapsulated the logic of the TimeService within a class and exposed the various methods to start, stop, pause, and continue the time service. The class is then compiled into a DLL, which I can test by creating a Windows or console application.

Pages: 1, 2

Next Pagearrow