Everytime I write a new Windows Service in .NET, I always forget the details and syntax for installing it and debugging it. For the last several years, I have been refering to the same article from Ken Getz because it has all the information I need to know.
.
Testing Your Service
Unlike many applications you'll create using Visual Studio .NET, you cannot simply run a Windows service from within the development environment. You must build the executable, install it, and test it as a running service. (Debugging a service is another story altogether, which I'll cover in the next section.) Follow these steps to test your Windows service:
Use the File Save All menu item, or press Ctrl+Shift+S, to save your entire project.
Choose the Build Build menu item (or press Ctrl+Shift+B) to build your service's executable file.
Find the executable. Use the Visual Studio .NET Command Prompt item from the Start menu. It's installed as a subitem of the Visual Studio .NET Tools item to open a Windows command prompt. (If you don't follow these steps, you won't have your MS-DOS path set correctly.) Change to the folder where your project is stored. Navigate to the bin\debug folder for C# projects, or the bin folder for Visual Basic projects, and locate the FileWatcher.exe file you've just created.
Install your service. Run the InstallUtil tool that comes with Visual Studio, using the following command line:
InstallUtil filewatcher.exe
Figure 12 shows the output of running the InstallUtil utility. InstallUtil runs a transactioned install. If anything fails as part of the install, all changes are rolled back. Unless you set the Account or Password and UserName properties of the ServiceProcessInstaller object, this installation will fail. If you want to view all the options available for this installation utility, run InstallUtil /?
Start the service. Unless you modified the ServiceInstaller1 StartType property, you'll need to start your service. Bring up the Windows service manager. (The exact steps depend on your operating system. In Windows 2000, you can use the Administrative Tools applet in Control Panel and select the Services item.) In the Services tool, find the FileWatcher service and double-click it to load the properties dialog box for the service. If you want to specify a path other than C:\ for the FileWatcher class, you can do that in the Start Parameters textbox. When you're ready, press Start to start the service.
Investigate the Startup events. Open the Event Viewer (again, the steps vary depending on your operating system). Select the Application log, and note that you should find two entries in the event log already. The first, sent from your service's OnStart event procedure, contains the text "FileWatchService starting. There are 0 args. Watch path is 'C:\'." (The text will be different if you specified an argument when you started the service.) The second, sent automatically (because you set the service's AutoLog property to True), indicates that the service started successfully.
Test the service. Open Windows Explorer, navigate to the folder your service is "watching," and make some changes. Rename, delete, or modify files. Switch back to the event viewer, and you should see information about your changes logged there.
Remove the service. When you're done, use the Services dialog box to stop your service. Run InstallUtil with its /u parameter to uninstall your service. You'll also need to shut down the Windows Services applet to completely remove your service from memory.
Debugging Your Service
At some point, you're likely to want to single-step through the code you've written in your service application. Although you can debug services much as you debug other applications, you cannot simply press F5 to start running the service from within the Visual Studio development environment, as you can with other projects.
Because you must compile and install a service before running it, debugging becomes a little more complex than for normal applications. Visual Studio .NET makes this process as easy as possible. Once your service is running, you can grab onto the running process and debug your code. To test this out, follow these steps:
Reinstall and start your service, as described in the previous section. (You must start the service running, or you won't be able to debug it.)
In Visual Studio, with your project loaded, select the Debug Processes menu item, displaying the Processes dialog box.
Select the Show system processes checkbox so that the Available Processes list includes running services.
In the Available Processes list, select the Filewatcher.exe entry, and then click Attach. On the Attach to Process dialog box, make sure that the Common Language Runtime option is selected, then select OK to accept. Then you can close the Processes dialog box.
Set a breakpoint in your code at the location you'd like to test. In this case, set a breakpoint on one of the event procedures you've created within the FileWatcher class.
Trigger the breakpoint by taking the necessary action within the file system. For example, if you set a breakpoint in the Created event procedure, creating a new folder in the "watched" folder should bring you back to your breakpoint. At this point, you can single-step through the code, as you would with any other application. Press F5 to continue running when you're finished with your testing.
When you're finished debugging, detach the debugger from the running process using the Debug Processes menu. Select the FileWatcher project in the list of debugged processes, then click the Detach button that's to the right of the list. Dismiss the dialog box.
Use the Debug Stop Debugging menu item to end the debugging session.
If you've gotten this far, you're most likely very happy to see that you can debug services so easily, but the nagging question about how you debug your service's OnStart event handler remains. Because you can't start debugging unless the process is running, and the OnStart event procedure runs when you start the service, how can you debug this code? One easy solution is to embed calls to EventLog.WriteEntry in the code, as pioneer coders might have done before the advent of adequate debugging tools.
Single-stepping though your startup code, however, will take a bit more effort. The .NET SDK explains that the OnStart method must return within 30 seconds, or the SCM will time out. If you must start the service and attach to it in order to debug, how do you grab onto the process before the Start event has completed?
One solution is to cheat—that is, insert a pause into the OnStart procedure, using code like this (I'll leave it to anyone using Visual Basic to remove the semicolon when inserting the following code into their class):
System.Threading.Thread.Sleep(25000);
This code causes the thread to sleep for 25 seconds. This is long enough for you to dig through the Debug Processes menu item, find the process you want to debug, and attach to it, but not so long that the SCM times out. Once you've added this code, you can step through your OnStart procedure.