Recently, I worked on project that required me to develop a custom C# Windows Service, and it had been a long time since I’d last created one. I forgot how tedious it is to do simple debugging. The way I’ve learned to debug a service is to build, install, run, and then attach to running process in Visual Studio. Sounds like a lot of work to do each time you need to test anything, right?
Instead, I will show you a very simple way to debug a Windows service. There are a few caveats with this approach, but I will get more into that at the end of the post.
Once you’ve created a Windows service project, or opened an existing one, open the Configuration Manager and add a new solution configuration. I usually copy from the debug configuration and name it “Debug NOSERVICE”. Then, configure it to build all projects and platforms needed.
Next, go to your project properties (Alt + Enter) and go to the “Build” tab. First, select the new solution configuration we just created. Then, add a conditional compilation symbol—you can name it anything you’d like. I usually go with “NOSERVICE”. This is so we can use the #if directive to indicate that a block of code should only be compiled when the symbol is defined.
After setting up the conditional symbol, open the service code, and create testing methods that mirror the service methods you wish to test. We will wrap them in a #if NOSERVICE directive so the compiler will only include this code if the symbol is defined.
We’re almost finished. Add a reference to System.Windows.Forms. Now, open the program.cs file and import System.Windows.Forms in the #if NOSERVICE directive. Within the Main method, add the #if NOSERVICE directive, and place the block to run the service into the “else” portion of the directive. In the “if” portion, we use the service class as an object, and run the testing methods while using a message box to keep it running.
This is a quick hack to debug a Window service project. As I mentioned above, there are a few caveats to debugging this way. This approach allows you to test the logic running in the service, but some objects won’t interact the same as if they were running in a real Window service. For example, if you have any queued items in a ThreadPool, the OnStop method won’t be called until the ThreadPool is empty. However, this hack can be especially useful when you need to debug small changes or step through the process. It’s come in handy for me and I hope it will help you.