Thursday, July 3, 2008

Debugging Windows Services in Visual Studio 2002/3/5/8

Just a quick tip on something I've been doing for years.

If you want to debug your Windows Service without having to install it as a service on your development machine first, you can use the "DEBUG" compiler constant to direct the compiler constant to run your service just as an executable instead of spinning up a service.

To do this in C# (basically the same steps in VB as well), open the Program.cs file and wrap the main method contents in a #if(!DEBUG), #else and #endif. Between the #else and #endif, simply put in the code that invokes the application logic.


You can see my example below, I've simply created a class called "ProcessFiles" and added static start and stop methods that starts/stops the processing as it normally would in a service. In the Program.cs file, i've then simply called the start method, put in a message box to stop the process falling through and stopping until developer debugging is read to quit, and a call to the stop method to cease processing.

From there it was just a simple matter of hooking up the OnStart and OnStop events of the actual service class of these methods as well.



namespace ExampleService
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
#if(!DEBUG)


ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service()
};
ServiceBase.Run(ServicesToRun);
#else
ProcessFiles.Start();
MessageBox.Show("Debugging has started. To stop debugging click ok");
ProcessFiles.Stop();

#endif

}
}
}


The "DEBUG" compliler constant is linked to the Build Properties Page on a C# project. By defualt this is ON for the "DEBUG" build configuration, but OFF for releases. You'll notice if you are looking at the code, that when your build configuration is set to "DEBUG:, the generated service code will be greyed out and the custom code comes to life. Switching to "RELEASE" config reverses this situation. Nice touch I think ;)

Now I can use the "RELEASE" config to build an exe so my solution can be deployed as a service for testing/production OR simply run it in the Visual Studio debugger under the "DEBUG" config without having to install it as a service on my dev machine.


Cheers

Matt.

3 comments:

KEXIN said...

This is a great tip but could you post what you have in the "ProcessFiles" class? Thanks!

KEXIN said...

This is great tip but could you post what you have in the "ProcessFiles" class?

Matthew Hunter said...

Sorry, there wasn't any real code behind that ! it was just an example. But, to give you an idea - ProcessFiles.Start could have been monitoring a directory for files and when one appears it could suck that data into a database. It would continue to run in a loop. When ProcessFiles.Stop is called, it might set a flag somewhere, so that next time ProcessFiles.Start runs through it's loop, it sees the flag and stops.

So, in summary, xxx.Start starts the processing (just like a regular service) and xxx.Stop and prepares the service for shutdown.