Debugging Windows Services
Pages: 1, 2
Now, create a new Windows application to test the DLL. In my Windows application, I need to add a reference to the DLL created above (see Figure 5).
|
| Figure 5: Creating a reference to the TimeService class |
Once it is done, add three buttons to the Windows form to Stop, Pause, and Continue the service.
I have the following global variables:
Dim timeservice As New TimeServiceClass.TimeService
Public Delegate Sub ServiceDelegate()
Note that I have created a delegate called ServiceDelegate() so that
I can invoke the timeservice object asynchronously in my form load event:
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles MyBase.Load
Dim async As New ServiceDelegate(AddressOf StartService)
async.BeginInvoke(Nothing, Nothing)
End Sub
The StartService() method simply starts the service by invoking the
StartService() method of the timeservice object:
Public Sub StartService()
timeservice.startService()
End Sub
Likewise, I do the same for the Stop, Pause, and Continue buttons:
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
' Stop the service
timeservice.stopService()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button2.Click
' Pause the service
timeservice.pauseService()
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button3.Click
' Continue the service
timeservice.continueService()
End Sub
You can now test your time service by running the Windows application, checking to see if you can stop, pause, and continue, your service.
Once you are sure that the service logic is working correctly, you can
use the service class in your actual Windows service. Here is the
code for the Windows service that uses the TimeService class (remember
to add a reference to the class):
Imports System.ServiceProcess
Public Class Service1
Inherits System.ServiceProcess.ServiceBase
Dim timeservice As New TimeServiceClass.TimeService
Public Delegate Sub ServiceDelegate()
Dim log As New System.Diagnostics.EventLog
'---------------------------------------------------------------
Protected Overrides Sub OnStart(ByVal args() As String)
Dim async As New ServiceDelegate(AddressOf StartService)
async.BeginInvoke(Nothing, Nothing)
Me.AutoLog = False
If Not EventLog.SourceExists("Time Service Log") Then
EventLog.CreateEventSource("Time Service Log", "MyLogFile")
End If
log.Source = "Time Service Log"
log.WriteEntry("Service Started")
End Sub
'---------------------------------------------------------------
Protected Sub StartService()
timeservice.startService()
End Sub
'---------------------------------------------------------------
Protected Overrides Sub OnStop()
timeservice.stopService()
log.WriteEntry("Service Stopped")
End Sub
'---------------------------------------------------------------
Protected Overrides Sub OnPause()
timeservice.pauseService()
log.WriteEntry("Service Paused")
End Sub
'---------------------------------------------------------------
Protected Overrides Sub OnContinue()
timeservice.continueService()
log.WriteEntry("Service Continued")
End Sub
End Class
You can now build the Windows service, install it, start it, and it should work correctly!
Summary
Encapsulating Windows services logic within a class allows you to debug the service easily, without the hassles of attaching a debugger to a running service. It is the recommended way to build Windows services. Using a combination of the techniques--attaching a debugger, encapsulating the service logic, and using the event log--will make life as a Windows service developer much easier and more productive.
Wei-Meng Lee (Microsoft MVP) http://weimenglee.blogspot.com is a technologist and founder of Developer Learning Solutions http://www.developerlearningsolutions.com, a technology company specializing in hands-on training on the latest Microsoft technologies.
Return to ONDotnet.com
You must be logged in to the O'Reilly Network to post a talkback.
Showing messages 1 through 12 of 12.
-
diagram of windows service
2006-04-25 21:54:30 Shilpi.gupta [Reply | View]
Can I have one diagramatic flow of windows services, explanation of which u r providing in this document. How we can make it multithreded?
-
How to OPEN service in the debugger?
2006-02-17 05:39:42 dekeli [Reply | View]
A staqndard windows service can be started in a debugger (such as windbg or ntsd) by setting the relevant registry entries (just like "Image File Execution Options" for standard exe)
Is it not supported for DotNet service?
-
How to OPEN service in the debugger?
2006-02-17 05:39:36 dekeli [Reply | View]
A staqndard windows service can be started in a debugger (such as windbg or ntsd) by setting the relevant registry entries (just like "Image File Execution Options" for standard exe)
Is it not supported for DotNet service?
-
How to OPEN service in the debugger?
2006-02-17 04:55:39 dekeli [Reply | View]
A staqndard windows service can be started in a debugger (such as windbg or ntsd) by setting the relevant registry entries (just like "Image File Execution Options" for standard exe)
Is it not supported for DotNet service?
-
Yet another way
2003-10-11 19:10:02 blowery [Reply | View]
The author's method doesn't really fix the problem with debugging code in the OnStart method of a service. You have to return from the method inside of 30 seconds, not just delegate to another function. After attaching the debugger, you're rarely going to have enough time to debug.
A better way is to use QueueUserWorkItem from System.Threading.Thread. You can delegate off your initialization code to a ThreadPool thread and enter the debugger there. Your OnStart method returns nice and quick and you can easily debug your application init logic from the other thread.
Crufty, but it works.
-
why bother with the DLL?
2003-09-29 10:00:32 anonymous2 [Reply | View]
While the previous poster makes a good point, I still think you gain a lot from being able to debug the code as a windows or console application.
But why bother splitting the code out to a DLL and creating a seperate test application to call it? It's pretty trivial to modify a service so that it'll run as a console app, and a lot less hassle. Just call your OnStart(), OnStop() etc from Main(). I generally just check the command line parameters for a value of "DEBUG", and run as a console app if it's present.
-
It's not either/or, it's both
2003-09-04 13:23:17 kez_higgins [Reply | View]
Wrapping your service up and running as a normal application is *not* the same as running as an actual service.
Services run with different priviledges to to user applications. They, generally anyway, can't interact with the desktop. If you're using COM to talk to another service there are security issues which may means your code will work as a service but not as an application (or vice versa). It affect interprocess communication via mutexes or events. That code you spent all week gleaming up, might plain not work as a service. I happned to me not three days ago, so I speak from uncomfortable experience here :)
It's true that attaching to a running service can be a bit fiddly, and you can't see what happens during start up, but sometimes it really is the only way to get a handle on what's happening.
-
It's not either/or, it's both
2004-03-02 10:26:49 amatlock [Reply | View]
I know this thread is pretty old, but I thought that I'd comment in case someone stubles across this looking for help.
I think that a combination of several approaches is optimal. I agree that the only way to accurately ensure that the code is going to execute properly is to debug it running as a service like kez_higgins says. I also spawn a new thread to execute my start up code like blowery mentions.
However, I take one more step and add a conditionally executed DEBUG block of code that causes the new thread to sleep for 10 seconds. This gives me enough time to attach to the process and step through the startup code if necessary.






Nice article. But when I tried the first method of attaching the process, when I click on the windows service the Attach button gets disabled. Also I could see the service Type as Managed. Can you help me with this issue?