Five ways debugging .NET Windows service
Although debugging a Windows service is not so easy, especially you want to step into OnStart codes, there still exist a couple of techniques to get it done. I compiled them here in order to let Internet searchers get their work done as easy as possible.
1. Sleeping reasonable time to let you attach the service process into Visual Studio.
Writing the first line of OnStart as “System.Threading.Thread.Sleep(25000);”, you’ll be able to have enough time to attach service process into Visual Studio. It’s a little annoying if you’re fast hand, because you have to wait some seconds before hitting your breakpoints. Life is short. (see ref.)
2. Using conditional directive to determine running in service or normal console mode.
By applying #if(!DEBUG)…(1)…#else…(2)…#endif on your Main method, you’ll be able to write service codes into (1) and the testing codes into (2). What does testing codes look like? Please see the following snippets. You can set breakpoints whichever line you want. (see ref.) Michael also mentioned checking "Environment.UserInteractive" to distinguish it's running under service mode. (for details, see comments below from Michael)
Service1 service = new Service1();
service.OnStart(null);
Console.ReadLine();
service.OnStop();
3. Breaking at service process runtime. (Thanks Paul Ballard's comment)
In debug mode, you can insert “System.Diagnostics.Debugger.Lauch() ;” before the codes where you'd like to be prompted debugger window. So once you start the service from SCM (Service Control Manager), the codes has chance being hit. It actually reminds me that Windows API -- "DebugBreak" or even lower level -- INT 3, both of them might do the same thing in unmanaged world. (see ref.)
4. Using self-built switcher to specify running in service or normal console mode.
Moving forward, if we add switcher in the program, which might be even convenient. For example, if we run “Service1.exe console”, it will silently run as console app, otherwise it just go ahead as service. The detail implementation is quite similar to the codes of #2. The only difference is that whether to run testing codes is based on the Main method's parameters instead of using conditional directive. The benefit of the approach is even in release mode, we are able to monitor the service status if we enable kind of tracking mechanism.
5. Building separate assembly.
Regardless any service or console context, we can simply build an assembly implementing kind of interfaces like Start, Stop, etc. We can test these methods by using unit test or any other test scenarios you want. Once it’s done, it’s basically OK for you to embed the assembly into a service project template created by Visual Studio. (for details, see comments below form Jack)
The only drawback of #2, 4 and 5 is that using normal console mode, the account of service might not be able to get tested, because it’s probably not launched as the account's privilege supposed to be, such as localsystem, networkservice, etc. For the account privilege tests, the #1 and 3 are still valid.
Happy compiling…
Comments
Anonymous
May 01, 2007
What we do is something like #2. You can check Environment.UserInteractive. If it's running as a service, it won't be. We also don't compile as Console. We use Windows Application, but if its UserInteractive, then we call AllocConsole to open up a console window for debugging and other fun.Anonymous
May 01, 2007
The comment has been removedAnonymous
May 02, 2007
Thanks for you guys' input. I already added you guys' techniques into the blog.Anonymous
July 21, 2008
The article, How to: Debug Windows Service Applications details how to attach to a running process toAnonymous
June 18, 2009
In the current project, I have to develop some windows services to sending out notification mails. The